我想触发一个任务在后台线程上运行。我不想等待任务完成。
在 .net 3.5 中,我会这样做:
ThreadPool.QueueUserWorkItem(d => { DoSomething(); });
在 .net 4 中,TPL 是建议的方式。我见过推荐的常见模式是:
Task.Factory.StartNew(() => { DoSomething(); });
但是,该StartNew()
方法返回一个Task
实现IDisposable
. 推荐这种模式的人似乎忽略了这一点。该Task.Dispose()
方法的 MSDN 文档说:
“在发布对任务的最后引用之前,请始终调用 Dispose。”
在任务完成之前,您不能对任务调用 dispose,因此让主线程等待并调用 dispose 将首先破坏在后台线程上执行的点。似乎也没有任何已完成/已完成的事件可用于清理。
Task 类的 MSDN 页面对此没有评论,《Pro C#2010...》一书推荐了相同的模式,对任务处理也没有评论。
我知道如果我只是离开它,终结器最终会抓住它,但是当我做很多火和忘记这样的任务并且终结器线程不堪重负时,这会回来咬我吗?
所以我的问题是:
Dispose()
在这种情况下不去上课是否可以接受Task
?如果是这样,为什么以及是否存在风险/后果?- 有没有讨论这个的文档?
- 或者是否有适当的方法来处理
Task
我错过的对象? - 还是有另一种使用 TPL 执行“开火即忘”任务的方法?