2016-04-29 216 views
0

我想澄清一下可能的代碼實現,以防在使用timerDoJob_Elapsed執行的代碼變長時它應該如何。 所以當下次計時器啓動時,所有的內部事物都會被篡改/取消等等。任務執行時間高於定時器執行時間

這種問題有什麼模式嗎? 任何線索,使其更加穩定?

private void timerDoJob_Elapsed(object sender, ElapsedEventArgs e) 
{ 
    VeryLongTask1(); 
    VeryLongTask2(); 
    VeryLongTask3(); 
} 
+0

你問,如果它怎麼取消任務會持續太久? –

+0

@SamIam不,我不是。其實任務應該及時完成,但下一次計時器的迭代不應該破壞以前的東西。 –

回答

1

如果您使用System.Timers.Timer,關閉AutoReset。然後在Elapsed方法結束時重新啓用計時器。

private void timerDoJob_Elapsed(object sender, ElapsedEventArgs e) 
{ 
    VeryLongTask1(); 
    VeryLongTask2(); 
    VeryLongTask3(); 
    mytimer.Enabled = true; 
} 

這樣,定時器甚至不會再次啓動,直到任務完成。但是請確保在try/catch塊中的Elapsed方法中包含所有內容,因爲如果發生未處理的異常,您的計時器將不會再次啓動。

我以前用過的另一種方法是在你經過的事件,使用鎖:

var myLock = new Object(); 
private void timerDoJob_Elapsed(object sender, ElapsedEventArgs e) 
{ 
    lock (myLock) { 
    VeryLongTask1(); 
    VeryLongTask2(); 
    VeryLongTask3(); 
    } 
} 

這樣,經過的事件的兩個實例不能在同一時間運行。但是,有一點需要注意:如果任務需要比定時器的兩次或更多次迭代更長的時間,則可以在後臺添加迭代。例如,如果您的計時器在5秒後過去了,但您的任務需要60秒才能完成,但在第一次完成時,您將有11次等待。

1

Timer.Change方法給予Timeout.Infinite0作爲參數會停止計時器(從MSDN):

如果duetime參數是零(0),回調方法被立即調用。如果 dueTime是Timeout.Infinite,則永遠不會調用回調方法; 定時器被禁用,但可以通過調用Change和 指定dueTime的正值來重新啓用。

一種可能,簡單卻不失強大的方法是停止計時器,直到整個任務已經結束,然後,再次啓動定時器:

private void timerDoJob_Elapsed(object sender, ElapsedEventArgs e) 
{ 
    timerDoJob.Change(Timeout.Infinite, 0); 

    // Use a try-finally so if some tasks throws an exception 
    // the timer will be re-enabled again anyway 
    try 
    { 
     VeryLongTask1(); 
     VeryLongTask2(); 
     VeryLongTask3(); 
    } 
    finally 
    { 
     timerDoJob.Change(0, 5000); 
    } 
}