29

Async/Await FAQ中,Stephen Toub 说:

awaitable是公开返回有效 awaiter 的方法任何类型。 ... awaiter是从awaitable的方法返回的任何类型,并且符合特定模式。GetAwaiter

GetAwaiter

所以为了成为一个awaiter,一个类型应该:

  • 实现INotifyCompletion接口。
  • 提供一个名为 的布尔属性IsCompleted
  • 提供一个返回or的无参数GetResult方法。voidTResult

我暂时忽略ICriticalNotifyCompletion

我知道我提到的页面有一个示例,该示例显示了编译器如何翻译等待操作,但我仍然很难理解。

当我等待一个awaitable时,

  • 什么时候IsCompleted检查?我应该在哪里设置它?
  • 什么时候OnCompleted调用?
  • 哪个线程调用OnCompleted
  • 我看到了直接调用 continuation 参数OnCompletedTask.Run(continuation)在不同示例中使用的示例,我应该选择哪个,为什么?
4

2 回答 2

16

为什么要自定义等待者?

await 您可以在此处查看编译器的解释。本质上:

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

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

从评论中编辑: OnCompleted应该将其参数安排为异步操作的延续。

于 2012-09-30T13:00:38.857 回答
6

在绝大多数情况下,您作为开发人员不必担心这一点。使用asyncandawait关键字,编译器和运行时会为您处理所有这些。

要回答您的问题:

代码何时检查 IsCompleted?我应该在哪里设置它?

IsCompleted当任务完成它正在做的事情时,任务应该设置。例如,如果任务正在从文件加载数据,则在加载数据IsCompleted并且调用者可以访问它时应该返回 true。

它什么时候调用 OnCompleted?

OnCompleted 通常包含一个由调用者提供的委托,以便在任务完成时执行。

它是并行调用 OnCompleted 还是 OnCompleted 中的代码应该是异步的?

OnCompleted 中的代码应该是线程中立的(不关心它是从哪个线程调用的)。这对于更新单线程公寓中的 COM 对象(如 Metro/Windows8/Windows Store 应用程序中的任何 UI 类)可能会有问题。它不必是异步的,但可以包含异步代码。

我看到了直接调用 OnCompleted 的 continuation 参数和在不同示例中使用 Task.Run(continuation) 的示例,我应该在什么时候使用?

尽可能使用async/ await。否则,请使用 Task.Run() 或 Task.Wait(),因为它们遵循大多数人习惯的顺序编程模型。可能仍需要使用延续,尤其是在您遇到公寓问题的 Metro 应用程序中。

于 2012-09-30T13:05:53.003 回答