2012-02-09 81 views
3

我已經創建了一個看門狗定時器(使用System.Windows.Forms.Timer),如果長時間沒有接收數據的小包到期觸發:集中停止的C#/啓動計時器

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()

由於每秒可能會有數百個數據包接收,並且由於應用程序的主要工作是響應這些數據包,我開始懷疑重置計時器是否不是CPU /操作系統密集型。

任何想法如何調用Timer.Stop()/Timer.Start()這種方式可能會影響性能(就延遲而言)?

+0

你願意做可能更好使用'System.Debug。秒錶「課程? – MattC 2012-02-09 18:45:35

回答

5

使用簡單的時間跨度或整數變量作爲標誌。當計時器打勾時,它會檢查秒錶對象,查看自從上一次使用標誌以來已經過了多長時間。如果它超過你的超時值,你會觸發你的看門狗代碼。

現在,而不是重置定時器,其他代碼可以直接使用秒錶,當一個新的包進入更新您的時間跨度標誌值。

你也應該要麼你的計時器的滴答間隔設置爲大約1/2您希望實際的超時時間長短,或者讓事件中的代碼設置您的間隔時間,以便您的下一個時間間隔事件僅在連接切斷後超時幾毫秒。否則,在最後一個數據包在tick事件發生後很快到達的情況下,最終可能會等待幾乎兩倍的超時時間。

+0

打我吧:-) – 2012-02-09 18:48:45

+1

不要使用'DateTime'!在夏令時轉換期間以及用戶更改時鐘時,您將遇到問題。程序啓動時,最好啓動一個「秒錶」,並在每次發送消息時保存其「Elapsed」值。然後,計時器滴答可以將當前的「經過」值與最後收到的消息值進行比較。 – 2012-02-09 18:50:03

+0

關於夏令時的好處 – 2012-02-09 18:50:31

0

任何想法如何調用Timer.Stop()/Timer.Start()

這種方式可能會影響性能(在延遲方面)?

的做到這一點所需的資源的量是不可能進行測量。除非您遇到性能問題,否則不要嘗試解決性能問題,至少應使用軟件來分析軟件以查看其是否存在實際問題。

2

順便提一下,另一種選擇是每當消息進入時設置一個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

一個更簡單的方法是調用更新接收數據包的共同lastPacketReceived值時看門狗類中的方法。然後,你只需要在每超時間隔蜱一次和當前時間進行比較的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; 
     } 
    } 
}