2015-12-05 2 views
0

Я Мессинг с С # Await/асинхронной, когда я написал следующую программу:Можно ли изменить свойства ui после ожидания в асинхронных методах?

using System; 
using System.Threading; 
using System.Threading.Tasks; 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Test(); 

     while (true) { } 
    } 

    static async void Test() 
    { 
     var t = Task.Run(()=> Thread.Sleep(1000)); 

     await t; 

     throw new Exception("This exception happens in a worker thread"); 
    } 
} 

Когда я запускаю эту программу, я могу ясно видеть в окне потока Visual Studio, что происходит исключение в Worker Thread, а не Main Thread, это заставляет меня поверить, что когда я жду задания, мой метод может быть закончен другим потоком.

Однако, когда я открываю новые окна формы приложения и добавьте следующий обработчик события:

async void button1_Click(object sender, EventArgs e) 
    { 
     var task = Task.Run(() => Thread.Sleep(1000)); 

     await task; 

     button1.Text = "I'm in the main thread!"; //this works 
    } 

Это работает, так что я замечаю, что в консольном приложении моя функция Test возобновляется рабочим потоком, в то время как в приложении Windows Forms он всегда возобновляется основным потоком.

Почему это? Это надежный?

+0

Когда вы ожидаете задачи, любое исключение, вызванное задачей, повторно создается в контексте, в котором оживает ожидание (т. Е. Поток пользовательского интерфейса в случае оконной программы). Это надёжно. –

+0

Да, я тоже что-то читал, но в консольном приложении, если я установил точку останова в новом приложении Exception и просмотрю окно потоков, я вижу рабочий поток как текущий поток –

ответ

2

Да. Это надёжно.

Когда вы делаете await, текущий SynchronizationContext захватывается так, что, когда он будет продолжать после await, этот контекст будет использоваться для выполнения кода.

В приложениях с графическим интерфейсом текущий SynchronizationContext представляет собой контекст, который будет выполнять код в потоке пользовательского интерфейса.

В консольных приложениях текущий SynchronizationContext равен null, поэтому задача продолжается в потоке потока.

Посмотрите на this blog post.

1

Да, это правильно и одно из предполагаемых применений async/await. Task, которое вы ожидаете, происходит асинхронно. Когда он возобновляется, он возобновляется в вызывающем потоке, который будет потоком пользовательского интерфейса в случае обработчика событий WinForms.

Обратите внимание, что это изменение можно изменить, используя Task.ConfigureAwait(False). Когда задача сконфигурирована таким образом, она не будет передавать управление обратно в исходный поток и вместо этого возобновит работу в потоке задачи.

Все это поведение зависит от текущего приложения SynchonizationContext. Некоторые типы приложений будут иметь разные контексты, которые могут тонко изменить поведение. Консольные приложения - хороший пример этого, поскольку они не устанавливают контекст синхронизации по умолчанию и будут возобновлены в потоке задачи. Вы можете изменить это, если хотите, создав контекст для консольного приложения, как показано на рисунке here.

2

Как я объясняю в своем async intro, по умолчанию await захватит «контекст» и возобновит выполнение его метода async в этом контексте.

Технически этот контекст SynchronizationContext.Current, если это не null, в этом случае это TaskScheduler.Current.

В повседневных условиях это означает, что контекст является контекстом пользовательского интерфейса, если этот метод работает в потоке пользовательского интерфейса; это контекст запроса ASP.NET, если метод обслуживает ASP.Запрос NET; и это, скорее всего, контекст пула потоков во всех других ситуациях.

Обратите внимание, что это по умолчанию Поведение. Вы можете указать, что метод не нужно возобновлять в своем контексте, ожидая результата ConfigureAwait(continueOnCapturedContext: false). В этом случае вполне вероятно, что остальная часть метода будет выполнена в потоке пула потоков; но технически это просто означает, что метод будет выполняться «где-то», и вам все равно, где.

Смежные вопросы