后台工作者和 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/内核)。

根本不要使用BackgroundWorkerElapsed 事件由线程池线程上的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 使用率的主要内容,如果未能解决你的问题,请参考以下文章

kvm如何让一个vcpu占用一个物理cpu

人脑是单CPU 但可以带后台线程(转)

Xcode 9,watchOS4,不再显示 15% 的后台 CPU 限制?

C#后台进程cpu负载使用PerformanceCounter

使用 MQTT 守护程序时 CPU 使用率高..!

UWP:为啥我的后台任务(使用 TimeTrigger)会超出 CPU 配额?