Как осуществляется возобновление ожидания? - PullRequest
6 голосов
/ 21 марта 2011

Я читал посты Эрика Липперта в блоге об асинхронности в C # 5 ( part 4 особенно актуально) и смотрел, как Anders PDC10 говорит на эту тему, и мне неясно, как продолжить асинхронные методы.возобновляются в однопоточном контексте.

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

Действительно ли асинхронный метод знает, что ему нужно выполнить то, что похоже на действие, зависящее от контекста, или это было упрощение?

В целом, как можно возобновить работу с асинхронных методов в одноммногопоточный контекст?Требуется ли планирование внутри одного потока?

Ответы [ 2 ]

7 голосов
/ 21 марта 2011

Ответ Джона, конечно, великолепен;Я подумал, что просто добавлю еще одну вещь.

Рассмотрим приложение WinForms с одной кнопкой на форме, которая запускает код при нажатии кнопки.

Что происходит, когда вы не нажатием кнопки?Ничего такого.Процесс существует, код выполняется, но, похоже, ничего не делает.На самом деле он обрабатывает сообщения в потоке пользовательского интерфейса и определяет, что ни одно из них не интересно, но не похоже, что он делает что-то интересное.

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

Сценарий асинхронности на одном потоке точно такой же.Продолжение - код «что делать после завершения задачи» фактически является «обработчиком события» события «задача выполнена».Когда задача завершается, она «нажимает кнопку» и помещает сообщение в очередь сообщений потока пользовательского интерфейса.Неважно, делает ли это это из потока пользовательского интерфейса или из потока завершения ввода-вывода или чего-то еще.Когда поток пользовательского интерфейса приступает к обработке этого сообщения, он вызывает продолжение.Точно так же, как когда поток пользовательского интерфейса приступает к обработке нажатия кнопки, он вызывает обработчик нажатия.

7 голосов
/ 21 марта 2011

Продолжение задачи знает, где продолжение должно быть запланировано - например, «любой поток пула потоков» или «поток пользовательского интерфейса».

Однако это поведение определяется «ожидающим» - на самом деле это не часть того, за что отвечает компилятор C #. Компилятор просто вызывает BeginAwait и передает продолжение; ожидающий возвращает логическое значение, указывающее, была ли задача уже завершена синхронно, или должен ли вызывающий выполнить возврат и позволить продолжению произойти асинхронно.

Итак, на данный момент это решение принимается ожидающим, возвращенным TaskEx, но я не удивлюсь, увидев, что все это в конечном итоге попадет в Task. Это может передавать такие вещи, как контекст синхронизации, который знает, как следует обрабатывать дальнейшие действия.

Я не совсем уверен, какой подлинно однопоточный контекст вы рассматриваете ... или вы думаете о ситуации, когда большая часть работы должна выполняться в одном потоке , но для асинхронного бита могут быть задействованы другие потоки (например, когда получен пакет HTTP, обработан в потоке порта завершения ввода-вывода, а ответ обработан обратно в потоке пользовательского интерфейса)?

...