定制等待傻瓜

在Async / Await FAQ中 ,Stephen Toub说:

等待是暴露GetAwaiter方法的任何类型,该方法返回有效的awaiter

awaiter是从等待GetAwaiter方法返回的任何类型,并且符合特定模式。

因此,为了成为awaiter ,类型应该:

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

我现在忽略了ICriticalNotifyCompletion

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

当我等待等待

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

你为什么想要一个定制的awaiter?

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

 var temp = e.GetAwaiter(); if (!temp.IsCompleted) { SAVE_STATE() temp.OnCompleted(&cont); return; cont: RESTORE_STATE() } var i = temp.GetResult(); 

从注释编辑: OnCompleted应将其参数安排为异步操作的延续。

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

回答你的问题:

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

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

什么时候调用OnCompleted?

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

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

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

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

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