2016-02-29 46 views
0

我目前使用這種方法初探:工人階級只調用一次

public class AskingForWorkClass 
{ 
    private static Timer _timer; 

    public void Start() 
     { 
      // catchup with outstanding work 
      DoWork(this, null); 

     _timer = new Timer { Interval = 1000 }; // one second 
     _timer.Elapsed += DoWork; 
     _timer.Start(); 
     } 

     private void DoWork(object sender, EventArgs e) 
     { 

     } 
} 

的目的是,當啓動時調用所有的優秀作品首次完成。之後,一個計時器被用來調用DoWork,它會檢查更多的工作。請注意,如果定時器最後一次調用仍然運行,我想阻止DoWork被定時器擊中。這可能嗎?基本上,DoWork應該只能由一個進程運行。

+0

停止DoWork上的定時器並在退出之前重新啓動... – Gusman

回答

1

你可以只啓動/在你的DoWork方法停止計時器:

private void DoWork(object sender, EventArgs e) 
{ 
    _timer.Stop(); 

    // .. do stuff ... 

    _timer.Start(); 
} 

注:這取決於你使用Timer類,您可能沒有StartStop,而是需要使用Modify方法,但你明白了。

UPDATE

因此,基於此意見是應該避免的DoWork任何事件執行兩次,無論Interval特性的解決方案。

public class AskingForWorkClass 
{ 
    private static Timer _timer; 
    private AutoResetEvent _event = new AutoResetEvent(true); 

    public void Start() 
     { 
      // catchup with outstanding work 
      DoWork(this, null); 

     _timer = new Timer { Interval = 1000 }; // one second 
     _timer.Elapsed += DoWork; 
     _timer.Start(); 
     } 

     private void DoWork(object sender, EventArgs e) 
     { 
      _event.WaitOne(); 

      // ... do stuff here ... 

      _event.Set(); 
     } 
} 

這裏會發生什麼事是,進入正題DoWork時,會等到事件已經被設置爲有信號狀態,並阻止當前線程,直到出現這種情況。請注意,事件new AutoResetEvent(true)的構造會在信號狀態中創建事件,因此第一次調用DoWork並不會永久阻止。

一旦WaitOne呼叫通過,事件會自動將自己設置回無信號狀態,這意味着將來呼叫DoWork方法將被阻止。最後,我們調用Set方法,該方法將事件重新置於信號狀態,直到下一個WaitOne調用。

+1

如果定時器間隔足夠小,仍然有可能執行兩次。最好將AutoReset設置爲false,然後在DoWork完成後調用_timer.Start()。 –

+1

@JesseWeigert同意,這是OP的一件好事。但基於他的示例代碼,我認爲這個解決方案很好,並且有一點簡單的優點。 – CodingGorilla

+0

我希望它是儘可能健壯( - : – cs0815