定制等待傻瓜
在Async / Await FAQ中 ,Stephen Toub说:
等待是暴露
GetAwaiter
方法的任何类型,该方法返回有效的awaiter 。
…
awaiter是从等待的GetAwaiter
方法返回的任何类型,并且符合特定模式。
因此,为了成为awaiter ,类型应该:
- 实现
INotifyCompletion
接口。 - 提供名为
IsCompleted
的布尔属性。 - 提供一个无参数的
GetResult
方法,该方法返回void
或TResult
。
( 我现在忽略了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
应将其参数安排为异步操作的延续。
在绝大多数情况下,作为开发人员,您不必担心这一点。 使用async
和await
关键字以及编译器和运行时为您处理所有这些。
回答你的问题:
代码何时检查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应用程序中。