SynchronizationContext и контекст выполнения
Каждый поток имеет связанный с ним контекст, он также известен как Текущий контекст , и эти контексты могут быть общими для всех потоков.ExecutionContext
содержит соответствующие метаданные текущей среды или контекста, в котором выполняется программа.
SynchronizationContext
представляет абстракцию, которая определяет местоположение, где выполняется код вашего приложения.SynchronizationContext
- это представление текущей среды, в которой выполняется наш код, оно предоставляет способ поставить единицу работы в контекст.SynchronizationContext
имеет контекст, связанный с ним, и в разных ситуациях разные структуры могут представлять разные вещи.Например,
- Winform Apps -
WindowsFormsSynchronizationContext
- WPF APS -
DispatcherSynchronizationContext
- Значение по умолчанию SynchronizationContext - по умолчанию (ThreadPool)
SynchronizationContext
- ASP.Net -
AspNetSynchronizationContext
Как await использует SynchronisationContext's
Async / await - просто волшебство компилятора, чтобы упростить создание асинхронных вещей (он не заставляет ваш код работать асинхронно), все, что он делает, когда видит await
, разбивает ваш метод на конечный автомат и когда вещь, которую вы ожидаете , завершает выполнение, конечный автомат возобновляется, и ваш код продолжает работать.Возобновление выполнения называется продолжением .
Особенность ключевого слова await
заключается в том, что он захватывает текущий SynchronizationContext
перед выполнением асинхронной операции, а затем отправляет продолжение к этому SynchronizationContext
, что означает, что если вы находитесь в потоке пользовательского интерфейса когда вы await
, после того как он завершится, то ваш код продолжит выполнение в потоке пользовательского интерфейса (который называется Выгрузка )
ConfigureAwait ()
Все ConfigureAwait(false)
делает, настраивает задачу так, чтобы продолжение после await
не нужно запускать в контексте вызывающей стороны.Это может иметь несколько преимуществ, одним из которых является небольшой выигрыш в производительности и более спорная остановка взаимоблокировок в определенных ситуациях.
Ответ
Каждый раз, когда вы вызываете await
, создается State Machine , чтобы сотворить чудеса Async Await Pattern и установить продолжение .
Только потому, что для ConfigureAwait
установлено значение false
вложенный в другой await
( конечный автомат ) не изменяет исходный вызов, который настроен на продолжение вызова Контекст синхронизации (если применимо).
Примечание: : someUIButton_click
запущено незамеченным, и у вас должна быть соответствующая проверка ошибок
Обновление
Так что это означает, что ямогу делать все, что захочу, в T1
, пока он не взаимодействует с некоторыми компонентами пользовательского интерфейса
Вы "на первый взгляд" имеете свободный доступ к компонентам пользовательского интерфейса из someUIButton_click
иT1
однако, за исключением того, что после await
в T1
вы настроили задачу так, чтобы продолжению не нужно было возвращаться в вызывающий контекст.Доступ к компоненту UI
здесь, вероятно, вызовет у вас проблемы.
Так что же после await
in someUIButton_click
?
Что ж, в этом случае задача имеет (по умолчанию)захватил текущий контекст (предположительно, ваш поток пользовательского интерфейса ), и продолжение будет продолжено в этом контексте.Каждое вложенное ожидание - это отдельный случай, и вызывающий await
(конечный автомат) выбирает, в каком контексте он продолжает