我需要处理任务吗?

Kev*_*han 17 .net dispose task-parallel-library

我很开心System.Threading.Tasks.但是,我看到的许多代码示例都是这样的:

Dim lcTask = Task.Factory.StartNew(Sub() DoSomeWork())
Dim lcTaskLong = Task.Factory.StartNew(Sub() DoSomeWork(), TaskCreationOptions.LongRunning)
Task.WaitAll(lcTask, lcTaskLong)
Run Code Online (Sandbox Code Playgroud)

这就是样本的范围.
任务实现IDisposable,显然我应该处理它们,但如果我只是想要"消防和遗忘"怎么办?

如果我不处理,我会泄漏线程/句柄/记忆/业力吗?我使用"错误"的任务吗?(应该只使用代理并单独留下任务吗?)

我可以处理ContinueWith()吗?(这好像在玩俄罗斯轮盘赌.)

Ree*_*sey 19

虽然通常的经验法则是始终要求Dispose()所有IDisposable实现,Task并且Task<T>通常有一种情况,最好让终结器处理这个问题.

Task实现的原因IDisposable主要是由于内部WaitHandle.这是允许任务继续正常工作所必需的,并且仅在任务上有延续时使用.如果没有延续,Task的Dispose方法没有实际效果 - 所以在这种情况下,它不是必需的.

话虽如此,在大多数情况下,有一个任务延续,通常非常非常难以以允许您正确调用Dispose()的方式编写代码.使用语句通常不适用于Task实例,因为Task调用本质上通常是异步的.过早地处理Task非常容易,尤其是在使用using语句时.

在你的情况下,如果保持对Task的引用并正确调用Dispose()相对简单,我会这样做.但是,如果这会导致您的逻辑变得更加复杂,我通常会假装Task不是IDisposable,并允许在Task的终结器中清除它.

有关更多详细信息,我建议在MSDN论坛上阅读此主题,其中Stephen Toub描述了Task为何详细实现IDisposable,并为上述建议提供了类似的指导.

  • 从您链接的Stephen Toub线程判断,当您说"[等待句柄]是必需的,以允许任务继续正常工作时,我认为您向后退,并且仅在任务有延续时使用.如果有没有延续,Task的Dispose方法没有实际效果......"但是根据Toub的说法,"Task.Dispose由于Task可能包装事件句柄而存在...如果你所做的只是使用continuation,那个事件句柄将会永远不会被分配,Dispose的价值会大大减少." 即你所暗示的相反. (3认同)