3

在我的应用程序中,我有一个“心跳”功能,目前在一个长时间运行的线程中以下列方式(伪代码)实现:

while (shouldBeRunning)
{
    Thread.Sleep(smallInterval);

    if (DateTime.UtcNow - lastHeartbeat > heartbeatInterval)
    {
        sendHeartbeat();
        lastHeartbeat = DateTime.UtcNow;
    } 
}

现在,当我的应用程序正在经历一些密集的 CPU 时间(CPU 占用率 > 90% 的几分钟的繁重计算)时,即使 smallInterval << heartbeatInterval,心跳也会延迟。

计算一些数字:heartbeatInterval 为 60 秒,lastHeartbeat 为 0.1 秒,报告的延迟最长可达 15 秒。因此,在我的理解中,这意味着当 CPU 非常繁忙时,睡眠(10)可以像睡眠(15000)一样持续。

我已经尝试将线程优先级设置为 AboveNormal - 如何改进我的设计以避免此类问题?

4

3 回答 3

4

有什么理由你不能为此使用计时器吗?您可以使用三种类型,我通常选择System.Timers.Timer. 以下文章讨论了这些差异:

http://msdn.microsoft.com/en-us/magazine/cc164015.aspx

本质上,计时器将允许您设置具有周期性间隔的计时器,并在该时间段过去时触发事件。然后,您可以使用调用sendHeartbeat().

计时器应该为您提供更好的服务,因为它们不会像您的睡眠线程一样受到 CPU 负载的影响。它的优点是代码更简洁(计时器设置非常简单易读),并且您不会有多余的线程。

于 2012-02-22T17:31:25.387 回答
3

您似乎正在尝试重新发明其中一个计时器类。

例如使用System.Timers.Timer怎么样?

var timer = new System.Timers.Timer(smallInterval);
timer.Elapsed += (s, a) => sendHeartbeat;
timer.Enabled = true;

这里的问题之一可能是,在 CPU 负载不足时,您的线程多久被调度一次。您的计时器实现本质上是单线程和块。移动到其中一个框架计时器应该可以缓解这种情况,因为(以上面的计时器为例)在线程池线程上引发了经过的事件,其中有很多线程池线程。

于 2012-02-22T17:33:17.600 回答
2

不幸的是,Windows 不是实时操作系统,因此几乎无法保证线程何时执行。唯一安排下一次唤醒线程的Thread.Sleep ()最早时间,当有空闲时间片时由操作系统唤醒线程。唤醒睡眠线程的确切标准可能没有记录,因此 Window 的内核团队可以根据需要更改实现。

我不确定 Timer 对象会解决这个问题,因为在计时器到期后仍需要激活心跳线程。

一种解决方案是提升心跳线程的优先级,以便它有机会更频繁地执行。

但是,心跳通常用于确定子系统是否陷入了无限循环,因此它们通常是低优先级的。当您有一个 CPU 密集型部分时,请Thread.Sleep (0)在关键点执行 a 以允许较低优先级的线程有机会执行。

于 2012-02-22T17:43:45.050 回答