最近在寫一個控制台程序,需要用到定時器,因為沒怎么寫過控制台程序,所以后來確定了使用System.Timers.timer定時器,在使用的過程中,也就遇到了些問題,比如: 我在主程序中設定了一個定時器,設置了該定時器的一些參數(如:間隔時間,啟動定時器,定時器的 Elapsed事件),然后在使用的時候,會發現當 Elapsed事件的執行時間超過了該定時器的間隔的話,會產生一些不好的后果,又或者當我們在該定時器的 Elapsed事件里面在設定一個定時器,當Elapsed事件的執行時間超過主定時器的間隔,也會產生不好的效果,這樣的話我們怎么來解決呢?然我們用代碼來看看。
首先我們來看下當 Elapsed事件的執行時間大於定時器的間隔的話,會發生怎樣的事情。
using System; using System.Collections.Generic; using System.Text; using System.Timers; namespace ConsoleTesk { class Program { static Timer timerOne = new Timer(); static int num = 0; static int i = 0; static void Main(string[] args) { timerOne.Interval = 1000 * 1;//設定定時器執行間隔為1s timerOne.Elapsed += new ElapsedEventHandler(timerOne_Elapsed); timerOne.Enabled = true; string readLine; do { readLine = Console.ReadLine(); } while (readLine != null && readLine != "exit"); } private static void timerOne_Elapsed(object source, ElapsedEventArgs e) { i++; if (i <= 5) { Method(); } } private static void Method() { Console.WriteLine(DateTime.Now.ToString()); Timer timerSecond = new Timer(); timerSecond.Interval = 1000 * 2;//設定定時器執行間隔為2s timerSecond.Elapsed += new ElapsedEventHandler(timerSecond_Elapsed); timerSecond.Enabled = true; } private static void timerSecond_Elapsed(object source, ElapsedEventArgs e) { Timer s = (Timer)source; Console.WriteLine("123456"); s.Enabled = false; s.Dispose(); } } }
編譯后運行得到的結果是:
我們能看到當Elapsed事件的執行時間大於定時器的間隔的話,很顯然得到的結果不是我們想要的,我找到的解釋是:
Elapsed 事件在 ThreadPool 線程上引發。如果 Elapsed 事件的處理時間比 Interval 長,在另一個 ThreadPool 線程中將會再次引發此事件。因此,事件處理程序應當是可重入的。那么我們怎樣才能達到我們想要的效果呢?修正后程序為:
using System; using System.Collections.Generic; using System.Text; using System.Timers; namespace ConsoleTesk { class Program { static Timer timerOne = new Timer(); static object lockNum = new object(); static object lockNum2 = new object(); static int num = 0; static int i = 0; static void Main(string[] args) { timerOne.Interval = 1000 * 1; //設定定時器的間隔為1s timerOne.Elapsed += new ElapsedEventHandler(timerOne_Elapsed); timerOne.Enabled = true; string readLine; do { readLine = Console.ReadLine(); } while (readLine != null && readLine != "exit"); } private static void timerOne_Elapsed(object source, ElapsedEventArgs e) { i++; if (i <= 5) { Method(); } } private static void Method() { timerOne.Enabled = false;//設置第一個定時器為停止 Console.WriteLine(DateTime.Now.ToString()); Timer timerSecond = new Timer(); timerSecond.Interval = 1000 * 4;//設定定時器的間隔為4s timerSecond.Elapsed += new ElapsedEventHandler(timerSecond_Elapsed); timerSecond.Enabled = true; } private static void timerSecond_Elapsed(object source, ElapsedEventArgs e) { num++; Timer s = (Timer)source; Console.WriteLine("123456"); if (num > 2) { s.Enabled = false; s.Dispose(); timerOne.Enabled = true;//當第二個定時器執行完畢后啟動后啟動第一個定時器 num = 0; } } } }
得到的結果是:
結果完全符合我們的要求。