我想触发一个在后台线程上运行的任务.我不想等待任务完成.
在.net 3.5中,我会这样做:
ThreadPool.QueueUserWorkItem(d => { DoSomething(); });
Run Code Online (Sandbox Code Playgroud)
在.net 4中,TPL是建议的方式.我见过的常见模式是:
Task.Factory.StartNew(() => { DoSomething(); });
Run Code Online (Sandbox Code Playgroud)
但是,该StartNew()方法返回一个Task实现的对象IDisposable.推荐这种模式的人似乎忽视了这一点.有关该Task.Dispose()方法的MSDN文档说:
"在释放对任务的最后一个引用之前,始终调用Dispose."
你不能在任务完成之前调用dispose,所以让主线程等待并调用dispose会首先打破后台线程上的操作.似乎也没有任何已完成/已完成的事件可用于清理.
Task类上的MSDN页面没有对此进行评论,并且"Pro C#2010 ..."一书推荐了相同的模式,并且没有对任务处理做出评论.
我知道如果我离开它,终结者最终会抓住它,但当我做了大量的火灾并且忘记了这样的任务并且终结者线程被淹没时,它会回来咬我吗?
所以我的问题是:
Dispose()就Task在这种情况下类?如果是这样,为什么会有风险/后果?Task我错过的物体?我想知道是否有关于处理嵌套在另一个一次性物品内的一次性物品的约定(在财产/公共领域,而不是私人成员).例如,DataSet包含DataTable,SqlCommand包含SqlConnection.
显而易见的是,一个班级处理它拥有的所有Disposable物品,剩下的就是其余部分.是否存在这样的惯例?如果是这样,.NET库如何确定谁拥有什么?如何确定是否正在处理嵌套对象?
PS:我一直想知道这个问题,显然有其他问题:调用SqlCommand.Dispose时会出现什么问题?
编辑1:发现配置DataSet,不配置其表.
// Fill dataset from sqldataadpater.
foreach (DataTable dt in dataSet.Tables)
{
dt.Disposed += Program.DisposedEventHandler2;
}
Console.WriteLine("Disposing dataset");
dataSet.Dispose(); //Event not fired here.
Console.WriteLine("Disposing datatables maually");
foreach (DataTable dt in dataSet.Tables)
{
dt.Dispose(); //Event fired here
}
#endregion
Run Code Online (Sandbox Code Playgroud)