在查看各种 C# Async CTP 示例时,我发现一些异步函数返回 void
,而另一些则返回非泛型的 Task
。 我可以理解返回 Task<MyType>
在异步操作完成后向调用方返回数据的有用性,但是我发现那些返回类型为 Task
的函数从来没有返回过任何数据。 为什么不返回 void
?
在查看各种 C# Async CTP 示例时,我发现一些异步函数返回 void
,而另一些则返回非泛型的 Task
。 我可以理解返回 Task<MyType>
在异步操作完成后向调用方返回数据的有用性,但是我发现那些返回类型为 Task
的函数从来没有返回过任何数据。 为什么不返回 void
?
如果调用者想要等待任务或添加后续操作。
事实上,只有在编写事件处理程序时才无法返回Task
的情况下,返回void
才是唯一的原因。
void
,你无法获取它生成的任务。(实际上,我不确定它是否真的生成了一个Task
) - SLaks返回Task
和Task<T>
的方法是可组合的——这意味着您可以在async
方法中await
它们。
async
返回void
的方法是不可组合的,但它们具有两个其他重要属性:
当您处理一个维护未完成异步操作计数的上下文时,第二点非常重要。
ASP.NET上下文就是这样的上下文;如果您在async
void
方法中没有等待来自async
Task
方法的结果,则ASP.NET请求将太早完成。
另一个上下文是我为单元测试编写的AsyncContext
(可在这里获取) - AsyncContext.Run
方法跟踪未完成操作计数,并在其为零时返回。
Task<T>
是任务并行库(TPL)的工作类型,它代表“将来会产生类型为T
结果的一些工作/任务”的概念。表示“将在未来完成但不返回结果的工作”由非泛型任务类型表示。T
的结果将如何生成是特定任务的实现细节;工作可能被分配到本地机器上的另一个进程,到另一个线程等。TPL任务通常从当前进程的线程池中分配给工作线程,但这种实现细节并不是Task<T>
类型的基本内容;相反,Task<T>
可以表示任何产生T
的高延迟操作。await
表达式的意思是“评估此表达式以获取表示将来产生结果的工作对象。注册当前方法的剩余部分作为与该任务继续关联的回调。一旦生成该任务并注册回调,立即将控制权返回给我的调用者”。这与常规方法调用相反/对比,后者意味着“记住你正在做什么,运行此方法直到完全完成,然后从你离开的地方继续,并知道方法的结果”。
async void
” 方法会在其开始执行时所处的同步上下文(SynchronizationContext
)上引发异常,类似于同步事件处理程序的行为。@DrewMarsh:UnobservedTaskException
和运行时设置仅适用于“fire and forget”的异步Task方法,而不适用于“async void
”方法。 - Stephen Cleary