使用 Thread.Sleep() 实现心跳

发布于 2025-01-08 07:02:36 字数 570 浏览 5 评论 0原文

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

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

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

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

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

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

in my application I have an "heartbeat" functionality that is currently implemented in a long running thread in the following way (pseudocode):

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

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

Now, it happens that when my application is going through some intensive CPU time (several minutes of heavy calculations in which the CPU is > 90% occupied), the heartbeats get delayed, even if smallInterval << heartbeatInterval.

To crunch some numbers: heartbeatInterval is 60 seconds, lastHeartbeat is 0.1 seconds and the reported delay can be up to 15s. So, in my understanding, that means that a Sleep(10) can last like a Sleep(15000) when the CPU is very busy.

I have already tried setting the thread priority as AboveNormal - how can I improve my design to avoid such problems?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

娇纵 2025-01-15 07:02:36

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

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

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

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

Is there any reason you can't use a Timer for this? There are three sorts you can use and I usually go for System.Timers.Timer. The following article discusses the differences though:

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

Essentially timers will allow you to set up a timer with a periodic interval and fire an event whenever that period ticks past. You can then subscribe to the event with a delegate that calls sendHeartbeat().

Timers should serve you better since they won't be affected by the CPU load in the same way as your sleeping thread. It has the advantage of being a bit neater in terms of code (the timer set up is very simple and readable) and you won't have a spare thread lying around.

怼怹恏 2025-01-15 07:02:36

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

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

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

据猜测,这里的问题之一可能是当 CPU 处于负载状态时线程被调度的频率。您的计时器实现本质上是单线程和块的。迁移到其中一个框架计时器应该可以缓解这种情况,因为(以上面的计时器为例)经过的事件是在线程池线程上引发的,线程池线程有很多。

You seem to be trying to reinvent one of the timer classes.

How about using System.Timers.Timer for example?

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

One of the issues here may be, at a guess, how often your thread gets scheduled when the CPU is under load. Your timer implementation is inherently single threaded and blocks. A move to one of the framework timers should alleviate this as (taking the above timer as an example) the elapsed event is raised on a thread pool thread, of which there are many.

醉城メ夜风 2025-01-15 07:02:36

不幸的是,Windows 不是实时操作系统,因此无法保证线程何时执行。 Thread.Sleep() 仅安排线程下次应该被唤醒的最早时间,由操作系统在有空闲时间片时唤醒线程。唤醒休眠线程的确切标准可能没有记录,以便 Window 内核团队可以根据他们认为合适的方式更改实现。

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

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

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

Unfortunately, Windows is not a Real Time OS and so there are few guarantees about when threads are executed. The Thread.Sleep () only schedules the earliest time when the thread should be woken up next, it is up to the OS to wake up the thread when there's a free time slice. The exact criteria for waking up a sleeping thread is probably not documented so that the Window's kernel team can change the implementation as they see fit.

I'm not sure that Timer objects will solve this as the heartbeat thread still needs to be activated after the timer has expired.

One solution is to elevate the priority of the heartbeat thread so that it gets a chance of executing more often.

However, heartbeats are usually used to determine if a sub-system has got stuck in an infinite loop for example, so they are generally low priority. When you have a CPU intensive section, do a Thread.Sleep (0) at key points to allow lower priority threads a chance to execute.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文