在.NET 4.0中,Task类暴露了IDisposable接口。Task可被回收(disposable)是为了清理IAsyncResult接口中AsyncWaitHandle属性暴露的等待句柄(wait handle)。在.NET 4.0中,等待句柄只有在读取AsyncWaitHandle属性,或者使用Task.WaitAll、Task.WaitAny时才会被创建,其他情况调用Task.Dispose都是多余的。
遗憾的是,.NET 4.0中的Task在处理ObjectDisposedException时显得过于武断:一旦调用Dispose释放等待句柄之后,即使其他属性与之毫无联系,剩余对象也会变得不稳定。
那么在.NET 4.0中是否应该调用Task.Dispose?
不应该,除非遇到以下情况:
整个Task不会被缓存;
等待句柄是通过调用Task.WaitAll、Task.WaitAny,或是读取IAsyncResult.AsyncWaitHandle创建而成;
Task上没有其他任务或线程处于等待状态。
其实,即使所有的条件都满足,你也不用做什么,因为终结器(finalizer)在清理等待句柄方面已经做了相同高效的工作。所以,除非你看到一些性能问题,否则你也许可以仍然不用回收task。
.NET 4.5核心中的改动
在.NET 4.5中,只有显式读取IAsyncResult.AsyncWaitHandle时,内部等待句柄才会被创建。其他部分,包括Task.WaitAll和Task.WaitAny都进行了重新设计,它们不再需要等待句柄。另外,随着语言中对async/await的支持,IAsyncResult在大部分场景中甚至都不再需要。
.NET 4.5中Task的另外一个改动是task在释放之后仍然可用。按照Stephen Toub的说法,“现在,即使Task释放之后也可以使用它的所有公开成员,并且它们使用起来就和释放之前一样。唯一一个不能使用的成员是IAsyncResult.AsyncWaitHandle,因为它是Task实例真正释放的部分。如果试图在Task释放后访问该属性,它会抛出一个ObjectDisposedException异常。”
虽然在.NET 4.5中调用Task.Dispose变得更加安全,但是几乎没有理由需要这么做。
针对.NET 4.5 Metro的特殊规则
Stephen Toub接着提到Task.Dispose在“.NET Metro风格应用程序”框架中甚至并不存在。要注意的是,目前关于此项设计变更的信息还未在WinRT的Task文档中更新反映。
从函数返回Task
在另外一篇题为“是否应当为同步方法暴露异步包装?”的文章中,Stephen深度探讨了从函数返回Task对象的话题。我们推荐你阅读全篇文章,而如果你时间不充裕,可以阅读以下的总结部分:
我认为只有那些异步方法比对应的同步方法拥有可扩展性(scalability)优势时才应当被暴露。异步方法不应当为了单纯地减轻负载(offloading)而进行暴露,因为这类优势可以通过使用专门用于异步执行同步方法的功能轻松实现,如使用Task.Run。
我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。
我原创,你原创,我们的内容世界才会更加精彩!
【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】
微信公众号
TechTarget
官方微博
TechTarget中国
相关推荐
-
.NET变得不可变
错误不可怕,可怕的是走进错误,但还不自知。你在编程时,是否也会走入无自知的误区呢?.NET开发中一个常见的误区,不知你是否已经走出?
-
.NET WCF 4.5 新功能介绍
在上周华盛顿州雷德蒙德的微软开发者大会,其中一个另从期待的项目就是.NET WCF 4.5新版本,它有哪些新功能?
-
更进一层的.Net事件跟踪机制
.NET 4.5刚刚发布不久,新增了EventSource和EventListener两个类,为那些使用Windows事件跟踪工具来记录事件的应用程序提供了一个更加简单的编程机制。
-
.NET 4.5中任务并行类库的改进
微软正在努力改进.NET 4.5中应用程序的性能,特别是使用任务并行类库(Task Parallel Library)的那些应用。接下来我会带你预览将要完成的改进内容。