[How to pass LongRunning flag specifically to Task.Run()?突出显示,特别是使用async
模式,将任务创建标志添加到较新的API中可能有点麻烦。
[我发现这篇文章声称无论如何都对async
来说不是一个好主意,因此不应使用:http://blog.i3arnon.com/2015/07/02/task-run-long-running/
我的理解是,该标志实际上将导致TPL启动专用线程,而不是给线程池施加压力,但是特别是如果我的应用程序不涉及很多并行任务,这真的很大吗?如果我期望的并行度小于默认线程池大小(无论是哪种大小),我是否可以安全地省略该标志-是最糟糕的情况,无论如何线程池可能会饿死几百毫秒?
线程池背后的整个想法是创建任务要花费几毫秒,因为它要求操作系统创建它,切换上下文等等……因此,为了处理它,框架创建了一些池并保留使用过的线程在那里供以后使用...
[是的,LongRunning标志很可能会导致创建新线程...这在新任务要花费更长的时间并且其中的线程创建时间并不重要时才有意义。
Threadpool有某些算法,如果您从那里集中处理大量线程并使它们忙碌,则可能决定将线程数量加倍假设您将要花越来越多的时间...因此,如果您要使线程池中的线程忙得足够长,您将不会从ThreadPool中获得任何好处,而是会得到一些开销。
因此忽略该标志不会破坏任何内容,但可能会带来一些开销。
在不传递LongRunning
参数的情况下调用Task.Factory.StartNew
方法时,默认情况下会省略[Task.Factory.StartNew
标志,因此您可以放心地假定忽略它是安全的”。实际上,忽略它比包含它更安全,因为此标志旨在作为一种性能优化技术,而不是日常用品。
通常,除非您发现自己确实需要它,否则请不要使用它。如果通过性能测试发现不使用
TaskCreationOptions
,通常只会使用LongRunning
,这会导致其他工作的处理出现长时间的延迟。 (citation)
[如果ThreadPool
因其线程被滥用而经常饿死(在等待I / O操作完成时被阻塞),则不要使用Task
标志修饰所有LongRunning
更简单,更有效的解决方法是,在应用程序初始化期间,使用方法ThreadPool
增加ThreadPool.SetMinThreads
线程的最小数量。例如:
ThreadPool.SetMinThreads
当您重构应用程序以正确使用异步时,更容易撤消此hack,而不是在代码中到处都撤消ThreadPool.SetMinThreads(workerThreads: 100, completionPortThreads: 5);
标志。