【问题标题】:What happens to work scheduled by Task.Run() after the program terminates?程序终止后 Task.Run() 安排的工作会发生什么?
【发布时间】:2012-12-30 01:05:59
【问题描述】:

我正在使用 TPL 和 async/await 进行一些测试,并注意到一些我发现意外的事情:例如,我正在安排工作以使用 lambdas 和 Task.Run 运行:

Task.Run(()=>Console.WriteLine("Nice program"));

然后我意识到如果程序立即返回,则永远不会执行工作。这是任何 .NET 应用程序(WPF、Forms 等)中的预期行为吗?有没有讨论这个的文档?

这意味着 Task.Run 实际上不适合一劳永逸的场景。

【问题讨论】:

  • 如果在调用 ExitProcess 的线程上运行,你可能会很幸运,否则我就走了。阅读here
  • @rene 我认为,在编写 .Net 应用程序时,Windows 进程如何终止并不是那么有趣。
  • @svick 好吧,这取决于我猜。您不能指望操作系统不必在运行于该操作系统之上的框架中提供一种功能(并且由于没有标记 Mono,因此 linux 在这里没有发挥作用)。所以我的评论肯定不是答案,但它可能有助于推理或理解行为。至少它对我有帮助……

标签: .net task-parallel-library


【解决方案1】:

根据定义,程序终止后,任何代码都无法运行。这与Task.Run()无关。

如果你实际上问的是这样的:

Tasks 在后台线程上运行,所以如果主线程完成(例如在用户关闭主窗口后),它们不能保证运行完成甚至启动,我该如何解决这个问题?

然后有两种选择:要么不让主线程完成(例如,按照 Jon Skeet 的建议调用 Task.WaitAll()),要么在前台线程上运行重要的 Tasks。为此,您可以使用 ParallelExtensionsExtras 中的QueuedTaskScheduler

【讨论】:

    【解决方案2】:

    这意味着 Task.Run 实际上不适合一劳永逸的场景。

    好吧,你不想想要忘记 - 你想等到它完成。所以请使用返回给您的Task

    为此,您需要跟踪以这种方式启动的所有未完成任务,然后在非后台线程中使用Task.WaitAll(tasks) 之类的内容。您可能不需要记住任务本身 - 您只需要有一个计数器,该计数器在每个任务完成时递减,然后您只需要等待它变为零。

    说实话,如果不了解您的场景,很难给出比这更具体的建议……但这样的事情肯定会奏效。

    当然,您可以轻松地将其封装在自己的便捷方法中。

    【讨论】:

    • 如果方法执行已经开始了怎么办?它中止了吗?
    • 我期待它的行为有点接近线程 - 程序在所有线程完成之前不会退出。我不明白线程和Task.Run 在做什么之间的概念区别。
    • @BrunoBrant 这不是真的,直到所有 foreground 线程都完成后程序才会退出。不同的是Tasks 通常运行在后台线程上。
    • @BrunoBrant:不,任务不是线程。它们通常更接近于“线程池操作”。
    猜你喜欢
    • 2013-06-18
    • 2015-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-28
    • 2021-04-10
    • 2020-08-02
    相关资源
    最近更新 更多