2013-02-13 70 views
5

我試圖使用Timer來觸發事件以通過網絡發送數據。我創建了一個簡單的類來調試。基本上我有一個List<string>我想發送。我想下面的情況發生:重置System.Timers.Timer以防止Elapsed事件

  1. 添加字符串List
  2. 開始Timer 10秒
  3. 添加第二個字符串ListTimer.Elapsed
  4. 重啓Timer回到10秒。

到目前爲止,我有這樣的:

public static List<string> list; 
public static Timer timer; 
public static bool isWiredUp = false; 

public static void Log(string value) { 
    if (list == null) list = new List<string>(); 
    list.Add(value); 

    //this does not reset the timer, elapsed still happens 10s after #1 
    if (timer != null) { 
     timer = null; 
    } 

    timer = new Timer(10000); 
    timer.Start(); 
    timer.Enabled = true; 
    timer.AutoReset = false; 

    if (!isWiredUp) { 
     timer.Elapsed += new ElapsedEventHandler(SendToServer); 
     isWiredUp = true; 
    } 
} 

static void SendToServer(object sender, ElapsedEventArgs e) { 
    timer.Enabled = false; 
    timer.Stop(); 
} 

任何想法?

回答

11

可以使用Stop功能由Start功能爲「重啓」定時器緊隨其後。使用該功能,您可以在首次創建類時創建Timer,然後在此時連線Elapsed事件,然後在添加項時調用這兩種方法。它將啓動或重新啓動計時器。請注意,在尚未啓動的計時器上調用Stop只會不做任何事情,它不會拋出異常或導致任何其他問題。

public class Foo 
{ 
    public static List<string> list; 
    public static Timer timer; 
    static Foo() 
    { 
     list = new List<string>(); 
     timer = new Timer(10000); 
     timer.Enabled = true; 
     timer.AutoReset = false; 
     timer.Elapsed += SendToServer; 
    } 

    public static void Log(string value) 
    { 
     list.Add(value); 
     timer.Stop(); 
     timer.Start(); 
    } 

    static void SendToServer(object sender, ElapsedEventArgs e) 
    { 
     //TODO send data to server 

     //AutoReset is false, so neither of these are needed 
     //timer.Enabled = false; 
     //timer.Stop(); 
    } 
} 

注意,而不是使用List要使用BlockingCollection<string>相反,它是非常有可能的。這有幾個優點。首先,如果多線程同時調用Log方法將會工作;因爲多個併發日誌可能會破壞列表。這也意味着SendToServer可以在添加新項目的同時將項目從隊列中取出。如果您使用List,則需要lock才能訪問列表(這可能不是問題,但不是那麼簡單)。

+0

從這個問題我明白,他想積累列表中的數據,並且只有自上次添加到列表已經過去10秒後才發送一次。他希望避免SendToServer被兩次調用兩次,如果他將數據添加到列表兩次相隔三秒。我可能是錯的,但是我就是這麼讀的。 – 2013-02-13 19:17:24

+0

@zespri這正是我閱讀它的方式。這正是這個代碼所做的。 – Servy 2013-02-13 19:20:02

+0

即使使用計時器..這是一個壞主意..沒有鎖定,沒有同步的形式..計時器是這樣做絕對最糟糕的方式,他應該重新考慮他是如何解決這個問題的。 – 2013-02-13 19:21:51

-4

你正在執行的是完全錯誤的做法。看一看消費者生產模式:

http://msdn.microsoft.com/en-us/library/hh228601.aspx

你所試圖做的是很通常被稱爲生產者/消費者數據流模型。從本質上講,您可以生成一些要發送到某個地方的數據列表,而不是每次將某個項目添加到要發送給它們的列表中時發送。因此,您有一個生產者(代碼將數據被髮送)和消費者(發送數據的代碼)。

通常這個問題是通過產生一個觀察列表的線程(通常是一個隊列)並以特定的時間間隔發送數據來解決的,最好的方法是使用EventWaitHandle。

下面是一些非常簡單的代碼爲例

class ServerStuff 
{ 
    public void Init() 
    { 
     datatosend = new List<string>(); 
        exitrequest = new EventWaitHandle(false, EventResetMode.ManualReset); //This wait handle will signal the consumer thread to exit 
     Thread t = new Thread(new ThreadStart(_RunThread)); 
     t.Start(); // Start the consumer thread... 
    } 

    public void Stop() 
    { 
     exitrequest.Set(); 
    } 

    List<string> datatosend; 
    EventWaitHandle exitrequest; 

    public void AddItem(string item) 
    { 
     lock (((ICollection)datatosend).SyncRoot) 
      datatosend.Add(item); 
    } 

    private void RunThread() 
    { 
     while (exitrequest.WaitOne(10 * 1000)) //wait 10 seconds between sending data, or wake up immediatly to exit request 
     { 
      string[] tosend; 
      lock (((ICollection)datatosend).SyncRoot) 
      { 
       tosend = datatosend.ToArray(); 
       datatosend.Clear(); 
      } 

      //Send the data to Sever here... 

     } 
    } 
} 
+0

您的鏈接顯示「此主題已過時」。並且不包含有用的信息。 – 2013-02-13 19:14:40

+0

我不知道你在說什麼或者該頁面應該告訴我什麼 – tedski 2013-02-13 19:26:29

+0

好的我會編輯和解釋更多... – 2013-02-13 19:27:00