计划但从未执行的任务会发生啥?
Posted
技术标签:
【中文标题】计划但从未执行的任务会发生啥?【英文标题】:What happens with scheduled but never executed tasks?计划但从未执行的任务会发生什么? 【发布时间】:2022-01-13 18:16:18 【问题描述】:参见以下示例:
public static void ForgottenTask()
Action<object> action = (object obj) =>
Console.WriteLine("Task=0, obj=1, Thread=2", Task.CurrentId, obj, Thread.CurrentThread.ManagedThreadId);
;
new Task(action, "alpha").ContinueWith(action);
static void Main(string[] args)
for (int i = 0; i < 1000000; i++)
ForgottenTask();
GC.Collect();
GC.Collect();
Debugger.Break();
显然没有执行任何操作,这是意料之中的。奇怪的是,当我在 Debugger.Break 期间通过菜单 -> 调试 -> Windows > 任务/并行堆栈检查任务时(在 Visual Studio 2022 中;我不知道有什么更简单的方法),我在 '计划的状态。我不确定它是调试限制还是调度程序的某种限制。那么我的第一个问题是,为什么是 10 000?
无论如何,这些任务不会被垃圾收集,这可能是预期的,因为它们在 TaskScheduler 中有引用。但我的问题是他们会发生什么?他们会永远挂在那里(听起来像内存泄漏)吗?或者它们会以某种方式被重复使用/移除?如果是这样,何时以及如何?
我在示例中使用了 .NET 6 和 VS 2022(如果相关)
【问题讨论】:
请阅读以下内容:1、2、3 顺便说一句,您应该尽量避免使用Task
构造函数。请首选Task.Run
或更多advanced scenarios TaskFactory.StartNew
。
@PeterCsala 我认为Task.Run
和Task.Factory.StartNew
都会消除内存泄漏,因为这些任务实际上会被执行。在这种情况下,任务永远不会执行,这就是它无法被清理的原因。
@PeterCsala:我读了前两个,但仍然不知道为什么。第三个似乎只是毫无疑问的答案(我觉得有点愚蠢,但我看不到那里的问题)。代码只是示例,我通常不会以这种方式创建任务。
@DavidL:我想这是真的,但这不是我原来的情况。我只是想提供一个完整的例子,它足够小而且容易。我最初的问题发生在 DataFlow 库中。 DataflowBlock 上有这个 Completion 属性link,它似乎是基于 TaskCompletionSource 的任务。当您不在块上调用完成时,此任务会泄漏。但我认为根本问题是一样的,我的例子似乎更容易展示。
【参考方案1】:
我不太了解使用 Visual Studio 的调试功能的含义,但是如果您在没有附加调试器的情况下运行程序(使用 Ctrl+F5),则垃圾收集器会正确回收这些任务。 ForgottenTask
方法内部创建的任务没有启动,因此它们没有被调度,并且由于您没有对这些任务进行任何显式引用,因此没有什么可以阻止垃圾收集器回收它们。以下是此行为的最小演示:
using System;
using System.Threading.Tasks;
public class Program
public static void Main()
var weakReference = ForgottenTask();
Console.WriteLine($"Before GC.Collect, IsAlive: weakReference.IsAlive");
GC.Collect();
Console.WriteLine($"After GC.Collect, IsAlive: weakReference.IsAlive");
static WeakReference ForgottenTask()
var task = new Task(() => ).ContinueWith(_ => );
return new WeakReference(task);
输出:
Before GC.Collect, IsAlive: True
After GC.Collect, IsAlive: False
Try it on Fiddle.
【讨论】:
很抱歉反应这么慢。我目前很忙,我想仔细检查您的答案,如果证明正确,我会接受。我不会是第一次调试器背叛我,但它总是突然冒出来一个惊喜。 @robot40q 哈哈!我个人很少被调试器背叛,因为我很少使用它。每次面对如此复杂的错误时,我都讨厌我的生活,以至于我别无选择,只能使用调试器。 :-)以上是关于计划但从未执行的任务会发生啥?的主要内容,如果未能解决你的问题,请参考以下文章
VB脚本手动运行完美,但无法通过计划任务管理器更新excel文件
windows2008定时计划任务未执行成功,报:因为用户未登陆到网络,因此未执行所有操作是啥原因导致?求助