在Async/Await FAQ中,Stephen Toub说:
等待是公开
GetAwaiter
方法的任何类型,该方法返回有效的 awaiter 。
...
awaiter 是从等待的GetAwaiter
方法返回的任何类型,并且符合特定模式。
因此,为了成为 awaiter ,类型应该是:
INotifyCompletion
界面。IsCompleted
的布尔属性。GetResult
方法,返回void
或TResult
。(我现在忽略ICriticalNotifyCompletion
。)
我知道我提到的页面有一个示例,显示了编译器如何转换等待操作,但我很难理解。
当我等待 等待时,
IsCompleted
?我应该在哪里设置它?OnCompleted
何时被召唤?OnCompleted
?OnCompleted
的延续参数,并在不同的例子中使用Task.Run(continuation)
,我应该去找哪些?为什么?答案 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)
在绝大多数情况下,作为开发人员,您不必担心这一点。使用async
和await
关键字以及编译器和运行时为您处理所有这些。
回答你的问题:
代码何时检查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应用程序中。