在任务上指定LongRunning有多重要?

时间:2020-02-10 08:49:28

标签: c# task-parallel-library

How to pass LongRunning flag specifically to Task.Run()?强调指出,尤其是使用async模式将任务创建标志添加到较新的API中可能有点麻烦。

我发现这篇文章声称无论如何async都不是个好主意,不应该使用:http://blog.i3arnon.com/2015/07/02/task-run-long-running/

我的理解是,该标志实际上将导致TPL启动专用线程而不是给线程池施加压力,但是特别是如果我的应用程序不涉及很多并行任务,这真的有很大的作用吗?如果我期望的并行度小于默认线程池大小(无论是哪种大小),我是否可以安全地忽略该标志-是最糟糕的情况,无论如何线程池可能会饿死数百毫秒?

2 个答案:

答案 0 :(得分:1)

线程池背后的整个想法是创建任务要花费几毫秒,因为它要求操作系统创建它,切换上下文等等……因此,为了处理它,框架创建了一些池并保持使用状态线程在那里供以后使用...

您是对的,LongRunning标志很可能会导致创建新线程...当新任务要花费更长的时间并且其中的线程创建时间并不重要时,这才有意义。

线程池具有某些算法,如果您从那里集中处理大量线程并使它们忙碌,则它可能会决定将线程数量加倍 假设您将要花越来越多的时间...因此,如果您要使线程池中的线程忙得足够长时间,您将不会从ThreadPool中获得任何好处,而是会得到一些开销。

因此,忽略该标志不会破坏任何内容,但可能会带来一些开销。

答案 1 :(得分:1)

在不通过传递LongRunning参数的情况下调用Task.Factory.StartNew方法时,默认情况下会省略TaskCreationOptions标志,因此您可以放心地假定忽略它是安全的 。实际上,忽略它比包含它更安全,因为此标志旨在作为一种性能优化技术,而不是日常用品。

通常,除非发现您确实需要它,否则不要使用它。如果通过性能测试发现不使用LongRunning,通常只会使用ThreadPool,这会导致其他工作的处理出现长时间延迟。 (citation)

如果Task因其线程被滥用而经常饿死(在等待I / O操作完成时被阻塞),则不要用{装饰所有LongRunning {1}}标志,一种更简单有效的解决方法是在应用程序初始化期间使用方法ThreadPool.SetMinThreads增加ThreadPool线程的最小数量。例如:

ThreadPool.SetMinThreads(workerThreads: 100, completionPortThreads: 5);

在重构应用程序以正确使用异步时,更容易撤消此黑客攻击,而不是在代码中到处都撤消LongRunning标志。