Подтвердить что ты не робот

Пользовательские ожидания для чайников

В Часто задаваемые вопросы по Async/Await, Стивен Туб говорит:

ожидаемый - это любой тип, который предоставляет метод GetAwaiter, который возвращает действительный awaiter....
awaiter - это любой тип, возвращаемый из метода awaitables GetAwaiter и который соответствует определенному шаблону.

Итак, чтобы быть awaiter, тип должен:

  • Внедрите интерфейс INotifyCompletion.
  • Предоставить логическое свойство, называемое IsCompleted.
  • Предоставьте безпараметрический метод GetResult, который возвращает void или TResult.

(Я игнорирую ICriticalNotifyCompletion).

Но для чего эти участники? Я знаю, что на той же странице, о которой я упоминал выше, есть образец, который показывает, как компилятор переводит ожидания, но я просто не понимаю.

Может ли кто-нибудь объяснить это как можно проще, как рассказать об этом 5-летнему ребенку?
Когда я жду ожидаемого,

  • Когда код проверяет IsCompleted? Где я должен установить его?
  • Когда он вызывает OnCompleted?
  • Вызывает ли он OnCompleted параллельно или должен быть асинхронный код внутри OnCompleted?
  • Я видел примеры прямого вызова параметра продолжения OnCompleted и использования Task.Run(continuation) в разных примерах, на что я должен идти и когда?
4b9b3361

Ответ 1

Зачем вам нужен пользовательский awaiter?

Вы можете увидеть интерпретацию компилятора await здесь. По существу:

var temp = e.GetAwaiter();
if (!temp.IsCompleted)
{
  SAVE_STATE()
  temp.OnCompleted(&cont);
  return;

cont:
  RESTORE_STATE()
}
var i = temp.GetResult();

Изменить комментарий: OnCompleted должен планировать свой аргумент как продолжение асинхронной операции.

Ответ 2

В подавляющем большинстве случаев вы, как разработчик, не должны беспокоиться об этом. Используйте ключевые слова async и await, и компилятор и среда выполнения будут обрабатывать все это для вас.

Чтобы ответить на ваши вопросы:

Когда код проверяет IsCompleted? Где я должен установить его?

Задача должна установить IsCompleted, когда задача завершит выполнение того, что она делает. Например, если задача была загружать данные из файла, IsCompleted должен возвращать значение true, когда данные загружаются и вызывающий может получить к нему доступ.

Когда он вызывает OnCompleted?

OnCompleted обычно содержит делегат, предоставленный вызывающим абонентом для выполнения, когда задача завершена.

Он вызывает OnCompleted параллельно или должен содержать код внутри OnCompleted будет асинхронным?

Код в OnCompleted должен быть нейтральным потоком (не заботьтесь о том, из какого потока он вызван). Это может быть проблематично для обновления COM-объектов в квартирах с одиночной резьбой (например, любые классы пользовательского интерфейса в приложениях Metro/Windows8/Windows Store). Он не должен быть асинхронным, но может содержать асинхронный код.

Я видел примеры как прямого вызова параметра продолжения OnCompleted и используя Task.Run(продолжение) в разных примерах, на что я должен идти и когда?

Используйте async/await, когда сможете. В противном случае используйте Task.Run() или Task.Wait(), потому что они следуют за последовательной моделью программирования, к которой привыкли большинство людей. Использование продолжений может потребоваться, особенно в приложениях Metro, где у вас проблемы с квартирой.