2009-05-02 40 views
12

我有一個計時器,需要不在同一時間處理其流逝的事件處理程序。但處理一個Elapsed事件可能干擾他人。我實施了以下解決方案,但感覺有些問題;看起來好像我應該使用不同的計時器或使用線程空間內的另一個對象。計時器似乎最適合,因爲我確實需要定期檢查狀態,但有時檢查時間會比我的時間間隔長。這是處理這個問題的最好方法嗎?如何在處理已經過的事件時阻塞計時器?

// member variable 
private static readonly object timerLock = new object(); 
private bool found = false; 


// elsewhere 
timer.Interval = TimeSpan.FromSeconds(5).TotalMilliseconds; 
timer.Elapsed = Timer_OnElapsed; 
timer.Start(); 


public void Timer_OnElapsed(object sender, ElapsedEventArgs e) 
{ 
    lock(timerLock) 
    { 
    if (!found) 
    { 
     found = LookForItWhichMightTakeALongTime(); 
    } 
    } 
} 
+2

這不應該是一個社區維基。 – Samuel 2009-05-02 16:39:09

+0

@Samuel - 如果海報需要,任何問題都可以是社區wiki。常見問題解答僅指定一些問題從一開始就應該是社區wiki,但不限制將CW應用於任何問題。 – tvanfosson 2009-05-02 16:43:38

+1

@tvanfosson:我讓他知道像這些問題不應該是社區維基。 – Samuel 2009-05-02 17:02:19

回答

13

您可以將AutoReset設置爲false,然後在完成處理後明確重置計時器。當然,你如何處理它取決於你期望定時器如何操作。這樣做會讓你的計時器偏離實際指定的時間間隔(就像停止和重新啓動一樣)。您的機制將允許每個時間間隔觸發並進行處理,但可能導致未處理的事件積壓,這些事件現在在計時器到期時導致處理程序被調用。

timer.Interval = TimeSpan.FromSeconds(5).TotalMilliseconds; 
timer.Elapsed += Timer_OnElapsed; 
timer.AutoReset = false; 
timer.Start(); 


public void Timer_OnElapsed(object sender, ElapsedEventArgs e) 
{ 
    if (!found) 
    { 
     found = LookForItWhichMightTakeALongTime(); 
    } 
    timer.Start(); 
} 
8

我通常在處理它時停止定時器,輸入try/finally塊,並在完成時恢復定時器。

0
timer.enabled = false 

timer.stop(); 

timer.enabled = true 

timer.start(); 
-1

我使用System.Threading.Timer像這樣

class Class1 
    { 
     static Timer timer = new Timer(DoSomething,null,TimeSpan.FromMinutes(1),TimeSpan.FromMinutes(1)); 

     private static void DoSomething(object state) 
     { 
      timer = null; // stop timer 

      // do some long stuff here 

      timer = new Timer(DoSomething, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1)); 
     } 



    } 
1

如果LookForItWhichMightTakeALongTime()是要花費很長的時間,我不會使用System.Windows.Forms.Timer因爲這樣做會鎖定你的UI線程,用戶可以殺死你的應用程序認爲它已經凍結了建議。

你可以使用的是一個BackgroundWorker(如果需要,還可以使用Timer)。

public class MyForm : Form 
{ 
    private BackgroundWorker backgroundWorker = new BackgroundWorker(); 

    public MyForm() 
    { 
    InitializeComponents(); 
    backgroundWorker.DoWork += backgroundWorker_DoWork; 
    backgroundWorker.RunWorkerCompleted += 
           backgroundWorker_RunWorkerCompleted; 
    backgroundWorker.RunWorkerAsync(); 
    } 

    private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) 
    { 
    e.Result = LookForItWhichMightTakeALongTime(); 
    } 

    private void backgroundWorker_RunWorkerCompleted(object sender, 
              RunWorkerCompletedEventArgs e) 
    { 
    found = e.Result as MyClass; 
    } 
} 

而且你甚至可以從你想隨時隨地RunWorkerAsync(),即使從Timer如果你想。並且只要確保檢查BackgroundWorker是否已在運行,因爲它在運行時會調用RunWorkerAsync()將引發異常。

private void timer_Tick(object sender, EventArgs e) 
{ 
    if (!backgroundWorker.IsBusy) 
    backgroundWorker.RunWorkerAsync(); 
} 
相關問題