当您在指定TaskCreationOptions.LongRunning
的同时创建Task
时,将专门为该任务创建一个新线程。如果不指定TaskCreationOptions.LongRunning
,则使用线程池。
请纠正我,如果我错了,但如果使用线程池,你不需要dispose()
任务(只要你没有在任务内使用任何同步对象,如Wait()
在子任务上)。
如果是这种情况,我是否负责清理使用TaskCreationOptions.LongRunning
标志创建的额外线程?
如果是,以下是可接受的模式:
var task = Task.Factory.StartNew(() => {...}, TaskCreationOptions.LongRunning);
task.ContinueWith(x => task.Dispose());
注意,ContinueWith
没有TaskContinuationOptions.LongRunning
,所以它应该使用线程池。
话虽如此,但是,我已经读到,将任务状态移动到Completed
, Faulted
或Cancelled
的线程运行延续的变化很大。
如果有人能指点一下,我会很感激的。
绝对不要在continuation中调用Dispose()
-你打算什么时候处理continuation任务?
我知道,Task
是可丢弃的唯一原因是清除在等待任务时创建的等待句柄。如果不等待任务,则永远不会创建等待句柄。在任何情况下,终结器最终都会被清除。
同样,如果任务创建了一个新线程,它将自己清理。
TaskContinuationOptions.LongRunning
是一个提示任务工厂/调度程序,事情并不像你描绘的那么固定。
我希望ContinueWith
在相同的(长运行)线程上执行,可能会或可能不会在ThreadPool上运行。
就我所知,Tasks的清理是自动的,所以我不会在这里使用Dispose()。
我不确定用LongRunning
选项创建的Tasks
的处置,但是关于您所展示的模式,有一些事情会出现在脑海中。
- 如图所示,没有观察到初始的长时间运行的
Task
,这意味着如果操作由于任何原因抛出Exception
,那么它最终将在Finalizer中被重新抛出,这将导致进程崩溃。 -
Task
的文档说你不应该调用Dispose
,除非Task
已经实际完成。所以你应该检查Task
是否在continuation中完成如果你要调用dispose。 - 你实际上是在
ContinueWith
返回的Task
上调用Dispose
,而不是原来的长时间运行的任务。
你可以这样做:
var task = Task.Factory.StartNew(() => {...}, TaskCreationOptions.LongRunning)
.ContinueWith(x =>
if(x.IsFaulted)
{
x.Exception.Handle(_ => true); //just an example, you'll want to handle properly
}
else if(x.IsCompleted)
{
//do something with the result, if necessary
x.Dispose());
});
最终,我认为遵守Task
比遵守Dispose
更重要。