返回void和返回一个Task有什么区别?
在查看各种C#asynchronousCTP示例时,我看到一些返回void
asynchronous函数,以及其他返回非通用Task
asynchronous函数。 我可以看到为什么在asynchronous操作完成时返回一个Task<MyType>
对于将数据返回给调用者是有用的,但是我所看到的具有返回typesTask
的函数永远不会返回任何数据。 为什么不回报void
?
SLaks和Killercam的答案是好的; 我想我只是添加更多的上下文。
你的第一个问题实际上是什么方法可以被标记为async
。
标记为
async
的方法可以返回void
,Task
或Task<T>
。 他们之间有什么区别?
一个Task<T>
返回的asynchronous方法可以等待,当任务完成时,它将提供一个T.
可以等待Task
返回的asynchronous方法,当任务完成时,将继续执行任务。
void
返回asynchronous方法不能等待; 这是一个“忘却”的方法。 它确实是asynchronous工作的,你没有办法告诉它什么时候完成。 这有点奇怪, 正如SLaks所说,通常你只会在做asynchronous事件处理程序的时候这样做。 事件触发,处理程序执行; 没有人会“等待”由事件处理程序返回的任务,因为事件处理程序不返回任务,即使他们这样做了,什么代码将使用该任务的东西? 通常不是用户代码首先将控制权交给处理程序。
你的第二个问题在评论中基本上是关于什么可以await
:
什么样的方法可以
await
? 是否可以await
void返回方法?
不,不能等待无效的退回方法。 编译器将await M()
转换为对M().GetAwaiter()
的调用,其中GetAwaiter
可能是实例方法或扩展方法。 等待的价值必须是一个你可以得到一个服务员的价值; 显然,一个返回空值的方法并不能产生一个你可以从中得到一个服务器的值。
Task
返回方法可以产生等待值。 我们预计第三方会希望创build自己的可以等待的Task
类对象的实现,并且可以等待它们。 但是,你将不能声明async
方法返回任何东西,但void
, Task
或Task<T>
。
(更新:我的最后一句话可能会被未来版本的C#篡改;有一个build议允许asynchronous方法的任务types以外的返回types。
(更新:上面提到的function使它成为C#7.)
如果主叫方想要等待任务或添加延续。
事实上,返回void
的唯一原因是如果你不能返回Task
因为你正在编写一个事件处理程序。
返回Task
和Task<T>
是可组合的 – 这意味着您可以await
async
方法中await
它们。
返回void
async
方法是不可组合的,但它们还有另外两个重要的属性:
- 它们可以用作事件处理程序。
- 它们代表“顶级”asynchronous操作。
当处理保持未完成asynchronous操作计数的上下文时,第二点非常重要。
ASP.NET的上下文就是这样一个上下文; 如果您使用asynchronousTask
方法而无需从asynchronousvoid
方法中等待它们,则ASP.NET请求将过早完成。
另一个上下文是我为unit testing编写的AsyncContext
(可在此处获得 ) – AsyncContext.Run
方法跟踪未完成的操作计数,并在零时返回。
typesTask<T>
是任务并行库(TPL)的主要types,它表示“将来产生typesT
的结果的一些工作/作业”的概念。 “将在未来完成但不返回结果的工作”的概念由非通用任务types表示。
T
types的结果是如何产生的是一个特定任务的实现细节; 该工作可能会被扩展到本地机器上的另一个进程,另一个线程等。TPL任务通常是从当前进程中的线程池出来的,而实现细节不是Task<T>
type; 而一个Task<T>
可以表示任何产生T
高延迟操作。
根据你上面的评论:
await
expression的意思是“评估这个expression式来获得一个表示将来产生结果的工作的对象,把当前方法的剩余部分注册为与该任务的继续相关的callback,一旦产生了这个任务并且调用返回注册, 立即返回控制给我的来电“。 这与普通的方法调用是相反的,这意味着“记住你在做什么,运行这个方法直到它完全结束,然后从你离开的地方拿起,现在知道方法的结果”。
编辑:我应该在2011年10月的MSDN杂志中引用Eric Lippert的文章,因为这对我理解这个东西是非常有帮助的。
对于加载更多infromation和whitepages看到这里 。
我希望这是一些帮助。