Интенсивный останов / запуск таймера C # - PullRequest
3 голосов
/ 09 февраля 2012

Я создал сторожевой таймер (с использованием System.Windows.Forms.Timer), который срабатывает, если длительный период времени истекает без получения небольшого пакета данных:

using System.Windows.Forms;
public class Watchdog
{
    private Timer Timer;

    public void Go()
    {
        Timer.Start();
    }

    public void Reset()
    {
        Timer.Stop();
        Timer.Start();
    }

    private void OnTimerExpired(object State)
    {
        Timer.Stop();
        DoSomething();
    }

    public Watchdog()
    {
        Timer = new Timer();
        Timer.Tick += new EventHandler(OnTimerExpired);
        Timer.Interval = (1000 * Timeout);            
    }
}

Основной код вызывает Go(), а затем вызывает Reset() при каждом получении пакета. Если таймер истекает, вызывается OnTimerExpired().

Поскольку в этом случае могут происходить сотни приемов пакетов в секунду, и поскольку основная задача приложения заключается в ответе на такие пакеты, я начинаю задумываться, не слишком ли сильно загружает таймер ЦП / ОС.

Есть идеи, как вызов Timer.Stop()/Timer.Start() таким образом может повлиять на производительность (с точки зрения задержки)?

Ответы [ 4 ]

5 голосов
/ 09 февраля 2012

Используйте простую переменную timepan или integer в качестве флага. Когда таймер тикает, он проверяет объект «Секундомер», чтобы увидеть, сколько времени прошло с момента последнего обновления флага. Если оно превышает значение тайм-аута, вы активируете свой сторожевой код.

Теперь, вместо сброса вашего таймера, другой код может просто использовать секундомер, чтобы обновить значение вашего флага времени, когда приходит новый пакет.

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

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

Другой вариант, кстати, просто иметь флаг Boolean, который устанавливается при поступлении сообщения. Обработчик события таймера проверяет этот флаг и предупреждает, если он не установлен. Итак, у вас есть:

private bool GotAMessage = false;

void MessageReceived()
{
    // happens whenever a message is received
    GotAMessage = true;
}

void OnTimerExpired(object state)
{
    if (!GotAMessage)
    {
        // didn't receive a message in time.
    }
    GotAMessage = false;
}
1 голос
/ 10 февраля 2012

Более простой вариант - вызвать метод класса WatchDog, который обновляет общее значение lastPacketReceived при получении пакета. Затем вам нужно только один раз запустить таймер в классе WatchDog, который помечается один раз за интервал времени и сравнивает текущее время со значением lastPacketReceived:

public static class WatchDog
{
    static object locker = new object();
    static long lastPacketReceived;
    static Stopwatch stopWatch = new Stopwatch();
    static long threshold = 5000;
    static WatchDog()
    {
        Timer watchDogTimer = new Timer(1000);
        watchDogTimer.Elapsed += new ElapsedEventHandler(watchDogTimer_Elapsed);
        watchDogTimer.Start();
        stopWatch.Start();
    }

    static void watchDogTimer_Elapsed(object sender, ElapsedEventArgs e)
    {
        lock (locker)
        {
            if ((stopWatch.ElapsedMilliseconds - lastPacketReceived) > threshold)
            {
                // threshold exceeded
            }
        }
    }

    public static void PacketReceived()
    {
        lock (locker)
        {
            lastPacketReceived = stopWatch.ElapsedMilliseconds;
        }
    }
}
0 голосов
/ 09 февраля 2012

Есть идеи, как звонить Timer.Stop() / Timer.Start()

Этот способ может повлиять на производительность (с точки зрения задержки)?

Нет

Количество ресурсов, необходимых для этого, вряд ли будет измерено.Если у вас нет проблем с производительностью, не пытайтесь решить проблему с производительностью, по крайней мере, используйте программное обеспечение для профилирования программного обеспечения, чтобы увидеть, является ли это реальной проблемой.

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