Реализация сердцебиения с Thread.Sleep () - PullRequest
3 голосов
/ 22 февраля 2012

в моем приложении у меня есть функция «сердцебиение», которая в настоящее время реализована в длинном потоке следующим образом (псевдокод):

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

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

Теперь, случается, что, когда мое приложение проходитПри некотором интенсивном времени ЦП (несколько минут интенсивных вычислений, в которых ЦП> 90% занят), сердцебиения задерживаются, даже если smallInterval << heartbeatInterval. </p>

Для сокращения некоторых чисел: heartbeatInterval равен 60 секундам, lastHeartbeatсоставляет 0,1 секунды, и заявленная задержка может составлять до 15 секунд.Итак, в моем понимании это означает, что Sleep (10) может длиться как Sleep (15000), когда процессор очень занят.

Я уже пытался установить приоритет потока как AboveNormal - как я могу улучшитьмой дизайн, чтобы избежать таких проблем?

Ответы [ 3 ]

4 голосов
/ 22 февраля 2012

Есть ли причина, по которой вы не можете использовать таймер для этого?Вы можете использовать три вида, и я обычно выбираю System.Timers.Timer.В следующей статье обсуждаются различия:

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

По существу, таймеры позволят вам установить таймер с периодическим интервалом и запускать событие всякий раз, когда этот период проходит.Затем вы можете подписаться на событие с делегатом, который вызывает sendHeartbeat().

. Таймеры должны служить вам лучше, так как они не будут подвержены нагрузке ЦП так же, как ваш спящий поток.Его преимущество в том, что он немного аккуратнее с точки зрения кода (настройка таймера очень проста и удобочитаема), и у вас не будет запасного потока.

3 голосов
/ 22 февраля 2012

Вы, похоже, пытаетесь заново изобрести один из классов таймеров.

Как насчет использования System.Timers.Timer , например?

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

Одна из проблем здесь может заключаться в том, как часто ваш поток назначается, когда процессор загружен. Ваша реализация таймера по своей сути однопоточная и блоковая. Переход к одному из таймеров фреймворка должен облегчить это, поскольку (на примере приведенного выше таймера приведено выше) истекшее событие возникает в потоке пула потоков, которых много.

2 голосов
/ 22 февраля 2012

К сожалению, Windows не является ОС реального времени, и поэтому существует мало гарантий относительно того, когда выполняются потоки.Thread.Sleep () планирует только самое раннее время, когда поток должен проснуться следующим, это зависит от ОС, чтобы разбудить поток, когда есть свободное время.Точные критерии для пробуждения спящего потока, вероятно, не задокументированы, так что команда ядра Windows может изменить реализацию так, как они считают нужным.

Я не уверен, что объекты Timer решат эту проблему как поток пульса до сих порнеобходимо активировать после истечения времени таймера.

Одним из решений является повышение приоритета потока пульса, чтобы он мог выполнять чаще.

Тем не менее, сердцебиения обычно используются для определения, например, застряла ли подсистема в бесконечном цикле, поэтому они обычно имеют низкий приоритет.Если у вас интенсивная загрузка ЦП, выполните Thread.Sleep (0) в ключевых точках, чтобы обеспечить возможность выполнения потоков с более низким приоритетом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...