Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 什么时候应该考虑任务;“长时间运行”吗;?_C#_.net_Task Parallel Library_Task_Threadpool - Fatal编程技术网

C# 什么时候应该考虑任务;“长时间运行”吗;?

C# 什么时候应该考虑任务;“长时间运行”吗;?,c#,.net,task-parallel-library,task,threadpool,C#,.net,Task Parallel Library,Task,Threadpool,在处理任务时,经验法则似乎是,线程池(通常由调用Task.Run(),或Parallel.Invoke())用于相对较短的操作。在处理长时间运行的操作时,我们应该使用TaskCreationOptions.LongRunning标志,以避免阻塞线程池队列,即将工作推送到新创建的线程 但究竟什么是长期运行的操作就时间而言,多长是多长?在决定是否使用LongRunning时,除了预期的任务持续时间之外,还有其他因素需要考虑,比如预期的CPU体系结构(频率、内核数等)或者从程序员的角度来看,一次尝试运

在处理任务时,经验法则似乎是,线程池(通常由调用
Task.Run()
,或
Parallel.Invoke()
)用于相对较短的操作。在处理长时间运行的操作时,我们应该使用
TaskCreationOptions.LongRunning
标志,以避免阻塞线程池队列,即将工作推送到新创建的线程

但究竟什么是长期运行的操作就时间而言,多长是多长?在决定是否使用
LongRunning
时,除了预期的任务持续时间之外,还有其他因素需要考虑,比如预期的CPU体系结构(频率、内核数等)或者从程序员的角度来看,一次尝试运行的任务数量

例如,假设我有500个任务要在专用应用程序中处理,每个任务需要10-20秒才能完成。我是否应该使用Task.Run(例如,在循环中)启动所有500个任务,然后等待它们全部执行(可能是
longlunning
),同时保留默认的最大并发级别?同样,如果我在这种情况下设置了
longlunning
,那么与省略
longlunning
相比,这是否会创建500个新线程,并实际导致大量开销和更高的内存使用率(由于分配了额外的线程)?这是假设在等待这500个任务时,不会计划执行任何新任务


我猜想,设置
LongRunning
的决定取决于在给定时间间隔内向线程池发出的请求数量,并且
LongRunning
只应用于那些预期花费的时间比大多数线程池放置的任务要长得多的任务-根据定义,最多只占所有任务的一小部分。换句话说,这似乎是一个队列和线程池利用率优化问题,应该通过测试逐一解决。我说的对吗?

您不应该在您的情况下使用
TaskCreationOptions.LongRunning
。我会用

如果您要创建大量任务,就不要使用
LongRunning
选项,就像您的情况一样。它用于创建将运行很长时间的两个任务


顺便说一句,我从来没有在任何类似的场景中使用过这个选项。

这没什么关系。问题不在于时间,而在于你的代码在做什么。如果您正在执行异步I/O,那么您只能在单个请求之间的短时间内使用线程。如果你在做CPU工作。。。嗯,你在用中央处理器。没有“线程池饥饿”,因为CPU得到了充分利用

真正的问题是当你在做不使用CPU的阻塞工作时。在这种情况下,线程池不足会导致CPU利用率不足——你说“我的工作需要CPU”,然后你就没有实际使用它

如果您没有使用阻塞API,那么使用
Task.Run
longlunning
没有任何意义。如果您必须异步运行一些旧的阻塞代码,那么使用
longlunning
可能是一个好主意。总工作时间不如“你多久做一次”重要。如果您基于用户单击GUI来启动一个线程,那么与单击按钮的动作中已经包含的所有延迟相比,成本很小,并且您可以使用
LongRunning
来避免线程池。如果您正在运行一个生成大量阻塞任务的循环。。。别这样。这是个坏主意:D

例如,假设没有异步API替代方案
File.Exists
。因此,如果您发现这给您带来了麻烦(例如,由于网络连接故障),您可以使用
任务。运行
-启动它,因为您没有做CPU工作,所以您可以使用
长时间运行

相比之下,如果您需要执行一些基本上100%CPU工作的图像处理,则不管操作需要多长时间,这不是一件长时间运行的事情

最后,使用
longlunning
最常见的场景是,当您的“工作”实际上是老派的“循环并定期检查是否应该做某件事,然后再循环”。长时间运行,但99%的时间只是阻塞一些等待句柄或类似的东西。同样,这只在处理不受CPU限制但没有适当异步API的代码时有用。例如,如果您需要编写自己的
SynchronizationContext
,您可能会发现类似的内容


现在,我们如何将其应用到您的示例中?我们不能,没有更多的信息。如果您的代码是CPU受限的,
并行。For
和friends是您想要的-它们确保您只使用足够的线程来饱和CPU,使用线程池也可以。如果它不受CPU限制。。。如果要并行运行任务,除了使用
LongRunning
,您实际上没有任何选择。理想情况下,这样的工作将由异步调用组成,您可以安全地调用并等待任务。当所有(…)来自您自己的线程时。

正如您所指出的,
任务创建选项。LongRunning
的目的是

允许线程池在一个任务长时间运行的情况下继续处理工作项

至于何时使用:

它本身并不是一个特定的长度……如果通过性能测试发现不使用它会导致其他工作处理中的长时间延迟,则通常只会使用LongRunning

在处理任务时,经验法则似乎是线程池(通常由调用Task.Run()或Parallel.Invoke()使用)应该用于