我和
System.Threading.Tasks
一起工作很开心。然而,我看到的许多代码示例看起来都是这样的:
Dim lcTask = Task.Factory.StartNew(Sub() DoSomeWork())
Dim lcTaskLong = Task.Factory.StartNew(Sub() DoSomeWork(), TaskCreationOptions.LongRunning)
Task.WaitAll(lcTask, lcTaskLong)
这就是样本的范围。
任务实现了
IDisposable
,所以显然我应该处理掉它们,但是如果我只想“即发即忘”怎么办?
如果我不处理,我会泄漏线程/句柄/内存/业力吗? 我使用任务“错误”吗? (应该只使用委托而不去管任务吗?)
我可以扔进
ContinueWith()
吗? (这看起来就像玩俄罗斯轮盘赌。)
虽然正常的经验法则是始终在所有
Dispose()
实现上调用 IDisposable
,但 Task
和 Task<T>
通常是最好让终结器处理此问题的一种情况。
Task 实现
IDisposable
的原因主要是由于内部的WaitHandle。这是允许任务延续正常工作所必需的,并且仅在任务有延续时使用。如果没有延续,则任务的 Dispose 方法没有实际效果 - 因此在这种情况下,不需要它。
话虽如此,在大多数存在任务延续的情况下,以允许正确调用 Dispose() 的方式编写代码通常非常非常困难。 using 语句通常不适用于 Task 实例,因为 Task 调用本质上通常是异步的。很容易过早地处理任务,尤其是在使用 using 语句时。
如果在您的情况下,保留对任务的引用并正确调用 Dispose() 相对简单,我会这样做。但是,如果这会导致您的逻辑变得更加复杂,我通常会假装 Task 不是
IDisposable
,并允许在 Task 的终结器中清理它。
有关更多详细信息,我建议阅读 MSDN 论坛上的此帖子,其中 Stephen Toub 详细描述了 Task 实现 IDisposable 的原因,并提供了与我上面的建议类似的指导。