.NET Task实例在运行期间是否超出范围?

Han*_*ank 42 .net c# garbage-collection task task-parallel-library

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

var task = new Task(() => DoSomethingLongRunning());
task.Start();
Run Code Online (Sandbox Code Playgroud)

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

Bru*_*ant 32

更新:

在我回答这个问题之后(很久以前!)我发现任务总是会完成 - 这是一个小的,让我们说"角落"的情况,任务可能无法完成.

原因是:正如我之前所回答的,任务基本上是线程; 但他们是后台线程.所有前景线程完成后,后台线程将自动中止.因此,如果您不对任务执行任何操作并且程序结束,则任务可能无法完成.

你应该总是在等待任务.更多信息可以在Jon给我优秀答案中找到.


原版的:

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

Thread文档:

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

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

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

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

希望能帮助到你.


¹根据文件:

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

  • 任务可以调度到任何 TaskScheduler,而不仅仅是 ThreadPool。 (2认同)

kem*_*002 13

任务将完成.即使没有任何其他引用(没有根据我认为是术语),线程池仍将保留对它的引用,并防止它至少被收集垃圾(至少我说,因为甚至完成后,无法保证收集垃圾,直到完成.

  • 为了更准确,TPL的任务调度程序将在任务运行时引用该任务.没有该引用,任务可能是垃圾收集,但这不会停止从完成运行的代码. (5认同)