后台工作者和 CPU 使用率
Posted
技术标签:
【中文标题】后台工作者和 CPU 使用率【英文标题】:Backgroundworker and CPU usage 【发布时间】:2015-10-12 04:55:42 【问题描述】:我需要每 20 秒做一些后台工作(它不必正好是 20000 毫秒,我可以允许延迟)。 我正在使用执行该函数的 Backgroundworker,然后使用 Timer 再等待 20 秒:
private readonly BackgroundWorker Worker = new BackgroundWorker();
volatile bool keepWorkerRunning;
Worker.DoWork += Worker_DoWork;
private void Worker_DoWork(object sender, DoWorkEventArgs e)
System.Timers.Timer aTimer = new System.Timers.Timer();
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Interval = 20000;
aTimer.Enabled = true;
keepWorkerRunning = true;
while (keepWorkerRunning) ;
aTimer.Enabled = false;
该工作器在软件运行期间一直处于活动状态。
问题是它占用了大部分 CPU。我注意到我的软件一直在使用大约 70% 的 CPU,只是停用 Backgroundworker,CPU 使用率下降到 0.5%。
如何在不使 CPU 过载的情况下完成相同的工作?
【问题讨论】:
为什么要同时使用定时器和BackgroundWorker?您可以在单个计时器的Tick
处理程序中执行您想做的事情,该计时器每 20 秒计时一次。此外,CPU 使用率的原因可能不是 BackgroundWorker/Timer 构造,而是您的繁忙循环 (while(true)
)
我记得从以前的一些帖子或答案中复制了这个结构。它完全可以完成我需要的工作,但它需要太多的 CPU 能力。您是否有其他需要更少的替代解决方案?请注意,它必须在与 UI 不同的线程上完成。
如果您真的想采用该解决方案,请将 while(keepWorkerRunning);
替换为 while(keepWorkerRunning) Threading.Thread.Sleep(100);
之类的东西,以摆脱占用全部 CPU 资源的繁忙循环。
扔掉 BackgroundWorker 并在 Timer 的 Elapsed 处理程序中执行后台工作,该处理程序在 ThreadPool 线程上运行。有关 Times.Timer 和 Threading.Timer 之间的区别,请参阅this question。
@LInsoDeTeh, Thread.Sleep(100)
对于那些王者来说是一个非常糟糕的解决方案。请不要这样做,也不要建议其他人这样做。
【参考方案1】:
CPU被这个循环吃掉了:
while (keepWorkerRunning);
您有效地指示 CPU 尽可能快地循环“什么都不做”。因此 70% 的 CPU 负载,可能会更糟(高达 100%,具体取决于您的 CPU/内核)。
根本不要使用BackgroundWorker
。 Elapsed
事件由线程池线程上的Timer
引发(计时器的SynchronizingObject
属性应为null),因此它将在后台运行。
更多信息您可以获取here。
更新: 根据要求,这是一个示例。
using System.Timers;
class MyClass : IDisposable
readonly Timer aTimer = new Timer(20000);
public void StartTimer()
this.aTimer.Elapsed += this.OnTimedEvent;
this.aTimer.Enabled = true;
void OnTimedEvent(object source, ElapsedEventArgs e)
// do your background work here
【讨论】:
好的,我会查找它,因为我不熟悉线程池。仅供参考,在 Backgroundthread 中使用 Thread.Sleep(20000) 之类的东西会消耗与现在一样多的 CPU? @Hamma,您无需将Thread.Sleep()
放入事件处理程序中,因为Timer
对象设法每20 秒调用一次您的处理程序。
你有我可以遵循的快速结构来实现定时器吗?
@Hamma 您已经拥有 Elapsed 处理程序 (OnTimedEvent
)。把你所有的背景代码放在那里。就是这样。
我能问一下为什么这是一个比System.Threading.Timer
更好的解决方案吗?以上是关于后台工作者和 CPU 使用率的主要内容,如果未能解决你的问题,请参考以下文章
Xcode 9,watchOS4,不再显示 15% 的后台 CPU 限制?