Когда вы вызываете асинхронный метод, он изначально синхронный.У него даже нет шансов быть асинхронным, пока он не достигнет ожидающего.
При каждом выражении ожидающего ожидания GetAwaiter()
вызывается ожидающим, которого вы ожидаете.Затем свойство IsCompleted
проверяется на ожидании.Если задача уже выполнена, метод продолжает работать синхронно.
В противном случае метод OnCompleted
вызывается для ожидающего, чтобы добавить к нему продолжение , которое затем вызывается обратно.когда задача завершена.Сам асинхронный метод возвращается вызывающей стороне в первый раз, когда он сталкивается с выражением ожидания, которое еще не завершено.
точный характер потоковой обработки этого зависит от задействованного ожидающего, нов асинхронной CTP для Task<T>
TaskAwaiter
будет использовать текущий планировщик задач для планирования продолжения.Для WinForms / Silverlight / WPF это означает, что если вы запускаете асинхронный метод в потоке пользовательского интерфейса, он продолжается в потоке пользовательского интерфейса.В противном случае (например, если вы уже находитесь в потоке пула потоков или используете его из консольного приложения), продолжение будет выполняться в потоке пула потоков.Конечно, вы можете изменить текущий планировщик задач самостоятельно, если вы действительно хотите.
Аналогично, разные ожидающие не имеют для планирования продолжений, используя TaskScheduler.Current
.Например, мои продолжения сопрограмм в основном сохраняют очередь продолжений для выполнения и продолжают идти, пока они не продолжатся.Мои продолжения ComeFrom оказались еще более причудливыми:)
Подробнее о том, как работает асинхронная функция под капотом, читайте в моей серии блогов Eduasync , которая довольно глубоко в нее углубляется.
Надеюсь, вам в целом нравится эта функция ... Я думаю, она невероятно увлекательна.