当使用 Task 对象进行即发即弃任务时,出现了问题:是否有必要调用 Dispose ()?
后台线程执行和Task.Dispose()
任务并行库 (TPL) 允许在后台线程上执行任务。通常,StartNew() 用于创建一个实现 IDisposable 的 Task 对象。根据 MSDN 文档,建议在释放对任务的最后一个引用之前调用 Dispose()。
处理后台任务的困境
但是,调用 Dispose() 需要要完成的任务,这违背了使用后台线程的目的。此外,没有可用于清理的完成事件。
不 Dispose() 可以接受吗?
根据 Microsoft 的 Stephen Toub 的说法,在大多数情况下,可以不对用于延续的 Task 对象调用 Dispose(),因为它们不会分配内部等待句柄。从 .Net 4.5 开始,只有显式使用 AsyncWaitHandle 才会导致等待句柄分配。
后果和风险
Toub 指出 Task 对象本身没有终结器。等待句柄有一个终结器,但仅在必要时才分配。因此,除非分配等待句柄,否则终结器不会执行。
但是,在创建许多即发即弃任务的情况下,如果多个任务,则终结器线程可能会被淹没。等待句柄已分配。
文档和最佳实践
MSDN 页面任务类没有明确解决这个问题。然而,Stephen Toub 的博客文章,标题为“我需要处置任务吗?”提供了进一步的说明,并建议在大多数情况下依靠最终确定。
替代方法
如果需要,可以通过多种方法检查等待句柄的可用性,并在已分配任务时将其处置。或者,人们可以探索“即发即忘”任务的其他选项,例如 ThreadPool.QueueUserWorkItem 方法或使用 .NET 的响应式扩展 (Rx)。
以上是我应该 Dispose() 一次性 TPL 任务吗?的详细内容。更多信息请关注PHP中文网其他相关文章!