53

如果我在方法中有以下代码块(使用 .NET 4 和任务并行库):

var task = new Task(() => DoSomethingLongRunning());
task.Start();

并且方法返回,该任务会超出范围并被垃圾收集,还是会运行完成?我没有注意到 GCing 有任何问题,但我想确保我没有为 GC 设置竞争条件。

4

2 回答 2

36

更新:

在我回答了这个问题之后(很久以前!),我发现任务总是运行到完成是不正确的 - 有一个小的,比如说“角落”案例,任务可能无法完成。

原因是这样的:正如我之前回答的那样,任务本质上是线程;但它们是后台线程。当所有前台线程完成时,后台线程会自动中止。因此,如果您对任务不做任何事情并且程序结束,则任务可能无法完成。

您应该始终等待任务。可以在Jon 给我的出色回答中找到更多信息。


原来的:

任务被调度到 ThreadPool,这意味着它们本质上是线程¹(实际上,它们封装了线程)。

线程文档

启动线程后,不必保留对 Thread 对象的引用。线程继续执行,直到线程过程完成。

所以,不,没有必要保留对它的引用。

此外,文档指出创建任务的首选方法是使用它的工厂:

您还可以使用 StartNew 方法在一次操作中创建和启动任务。如果创建和调度不必分开,这是创建和启动任务的首选方式 (...)

希望能帮助到你。


¹根据文档

任务表示异步操作,在某些方面它类似于创建新线程或 ThreadPool 工作项,但抽象级别更高。

于 2010-05-06T17:11:32.120 回答
16

该任务将运行完成。即使没有任何其他对它的引用(我相信没有被生根是这个词),线程池仍然会持有对它的引用,并至少防止它被垃圾收集(我至少说,因为即使完成后,不能保证它会被垃圾收集)直到完成。

于 2010-05-06T16:47:03.847 回答