定制等待傻瓜

时间:2012-09-30 12:46:33

标签: c# .net asynchronous .net-4.5 async-await

Async/Await FAQ中,Stephen Toub说:

  

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

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

  • 实施INotifyCompletion界面。
  • 提供名为IsCompleted的布尔属性。
  • 提供无参数GetResult方法,返回voidTResult

我现在忽略ICriticalNotifyCompletion

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

当我等待 等待时,

  • 何时检查IsCompleted?我应该在哪里设置它?
  • OnCompleted何时被召唤?
  • 哪个帖子调用OnCompleted
  • 我看到两个例子直接调用OnCompleted的延续参数,并在不同的例子中使用Task.Run(continuation),我应该去找哪些?为什么?

2 个答案:

答案 0 :(得分:13)

为什么要定制awaiter?

您可以看到编译器对await here的解释。基本上:

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

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

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

答案 1 :(得分:5)

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

回答你的问题:

  

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

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

  

什么时候调用OnCompleted?

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

  

是否并行调用OnCompleted或代码   在OnCompleted里面是异步的吗?

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

  

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

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