重的TPL后台线程会导致WPF的UI线程出现延迟

4

我有一个WPF应用程序,使用多个后台线程来预编译LINQ查询和预缓存一些稍后需要的值。TPL用于通过以下方式启动这些任务:

var newTask = new Task(taskAction, myCancelToken, TaskCreationOptions.LongRunning);
newTask.Start();

这个程序可以运行,任务分发到了多个CPU核上。然而,这些线程引起了高CPU负载,这在UI上是可感知的,会导致界面阻塞甚至冻结,只要线程没有完成。
那么,有没有合理的方法来使UI更顺畅呢?通过研究,我发现不应该给线程特殊优先级。其他人认为频繁使用Thread.Sleep()是一种解决办法,但我认为这种方法已经过时且不太好用。
还有其他方法我不知道吗?是否存在线程优先级方面的实际缺点(据我所知,这在TPL中直接是不可能的)?
提前感谢!

1
"TaskCreationOptions.LongRunning" 会创建新的线程,而不是使用线程池。您要启动多少个线程?您的目标计算机有多少个核心? - Nick Butler
我正在启动大约十到十二个任务。LongRunning模式只是一个尝试,我开始时没有使用它,但结果相同。核心数量可能不同,因为没有特殊的专用目标系统设置。 - Andreas H.
2个回答

1

1
我读到过不建议更改线程优先级的文章。但是为什么呢,既然它实际上是可能的?那么这是否意味着,如果有很多后台工作要做,我只能忍受性能较差的用户界面? - Andreas H.

0

在一个4核机器上,10个线程太多了。如果它们像预编译查询一样是计算密集型的,它们将争夺CPU时间,并使整个机器无响应。

我建议您使用Environment.ProcessorCount来查找可用的核心数,并一次只启动(该数字-1)个线程。您可以优先考虑哪些工作先运行,并将其他工作排队作为延续。

这将留出一个核心来服务于您的UI线程,并应使应用程序再次响应。


1
但是,TPL不是设计为将其任务分布在计算机设置和性能(包括CPU/核数)根据的一定数量的线程上吗?因此,我的意思是我启动了大约12个任务,而不是12个工作线程。同时,我删除了TaskCreationOptions.LongRunning,但正如我所说,这没有任何影响。 - Andreas H.
2
当您指定 LongRunning 时,您正在表示您想要一个新线程,并且希望它立即运行。如果使用普通任务,则会受到线程池线程注入/退役算法的影响,该算法具有自己的想法,但始终尝试使用整个机器。我建议始终保留一个核心空闲,这需要您手动安排。 - Nick Butler
因此,这导致编写一个自定义的TaskScheduler,限制并发线程数为ProcessorCount-1。 - Andreas H.
你可以使用这个链接中的一个:http://msdn.microsoft.com/en-us/library/ee789351.aspx - Nick Butler
这个答案完全不正确,一台计算机可以运行许多1000xCPU核心线程。当然,如果你超载了CPU,你的程序就会开始出现延迟,只有当你达到100%的CPU使用率时才会发生这种情况。除此之外,UI线程比后台工作线程具有更高的优先级。 一个线程不会阻塞一个核心直到它完成,每个线程都被赋予一定的工作时间,然后才会转移到下一个线程。 - Androme

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接