Найти в Дзене
using Dev

Поговорим о ConfigureAwait ч.3

Как SynchronizationContext и TaskScheduler связаны с await? Рассмотрите возможность написания приложения пользовательского интерфейса с расширением Button. Нажав на кнопку Button, мы хотим загрузить некоторый текст с веб-сайта и установить его как Button's Content. Доступ к Button должен быть возможен только из потока пользовательского интерфейса, которому он принадлежит, поэтому, когда мы успешно загрузили новый текст даты и времени и хотим сохранить его обратно в Button, Content нам нужно сделать это из потока, которому принадлежит элемент управления. Если мы этого не сделаем, мы получим исключение вроде: Если бы мы записывали это вручную, мы могли бы использовать, SynchronizationContext как показано ранее, для маршалирования настройки back Content в исходный контекст, например, с помощью TaskScheduler: или используя SynchronizationContext напрямую: Однако оба этих подхода явно используют обратные вызовы. Вместо этого мы хотели бы написать код естественным образом с помощью async/aw

Как SynchronizationContext и TaskScheduler связаны с await?

Рассмотрите возможность написания приложения пользовательского интерфейса с расширением Button. Нажав на кнопку Button, мы хотим загрузить некоторый текст с веб-сайта и установить его как Button's Content. Доступ к Button должен быть возможен только из потока пользовательского интерфейса, которому он принадлежит, поэтому, когда мы успешно загрузили новый текст даты и времени и хотим сохранить его обратно в Button, Content нам нужно сделать это из потока, которому принадлежит элемент управления. Если мы этого не сделаем, мы получим исключение вроде:

-2

Если бы мы записывали это вручную, мы могли бы использовать, SynchronizationContext как показано ранее, для маршалирования настройки back Content в исходный контекст, например, с помощью TaskScheduler:

-3

или используя SynchronizationContext напрямую:

-4

Однако оба этих подхода явно используют обратные вызовы. Вместо этого мы хотели бы написать код естественным образом с помощью async/await:

-5

Это «просто работает», успешно настроившись Content на поток пользовательского интерфейса, потому что, как и в случае с версией, реализованной вручную выше, awaiting Task по умолчанию обращает внимание на SynchronizationContext.Current, а также на TaskScheduler.Current. Когда вы awai-е что-то на C#, компилятор преобразует код, чтобы запросить (посредством вызова GetAwaiter) «awaitable» (в данном случае Task) для «awaiter» (в данном случае a TaskAwaiter<string>). Этот ожидающий отвечает за подключение обратного вызова (часто называемого «продолжением»), который будет возвращаться в конечный автомат после завершения ожидаемого объекта, и он делает это, используя любой контекст/планировщик, который он захватил в момент обратного вызова. зарегистрирован. Хотя это и не совсем тот код (есть дополнительные оптимизации и настройки), но он выглядит примерно так:

-6

Другими словами, сначала он проверяет, есть ли сет, а если нет, то есть ли в SynchronizationContext нестандартный набор . TaskScheduler Если он его найдет, то когда обратный вызов будет готов к вызову, он будет использовать захваченный планировщик; в противном случае он обычно просто выполняет обратный вызов как часть операции, завершающей ожидаемую задачу.

Источник

to be continued...