定制等待傻瓜

Şaf*_*Gür 25 .net c# asynchronous async-await .net-4.5

Async/Await FAQ中,Stephen Toub说:

一个awaitable是任何类型的,它公开GetAwaiter它返回一个有效的方法awaiter.
...
一个awaiter任何从一个返回类型awaitableGetAwaiter方法和符合特定的图案.

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

  • 实现INotifyCompletion接口.
  • 提供一个名为的布尔属性IsCompleted.
  • 提供一个GetResult返回void或无参数的方法TResult.

(我现在忽略ICriticalNotifyCompletion了.)

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

当我等待awaitable,

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

Ste*_*ary 13

你为什么想要一个定制的等待者?

你可以在await 这里看到编译器的解释.实质上:

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

cont:
  RESTORE_STATE()
}
var i = temp.GetResult();
Run Code Online (Sandbox Code Playgroud)

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


akt*_*ton 5

在绝大多数情况下,作为开发人员,您无需担心。使用asyncand await关键字,编译器和运行时将为您处理所有这一切。

要回答您的问题:

代码什么时候检查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应用中。