有時候我們需要實現延遲執行,或者是定時執行,這個時候可以使用System.Threading.Timer
Timer4個參數
TimerCallback callback:執行的函數,需要傳入一個object類型的參數
object state:callback傳入的參數的值,如果沒有的話寫成null
int dueTime:延遲執行的時間,即幾毫秒后執行操作,單位毫秒
int period:定時執行的時間,即每隔幾毫秒后執行一次操作,單位毫秒
如果要實現延遲執行的效果,那就傳入dueTime,並且把period設置成-1或者Timeout.Infinite
/// <summary> /// 延遲3秒后執行 /// </summary> static void Test1() { Console.WriteLine(DateTime.Now + " 開始..."); Timer timer = new Timer(args => { try { Console.WriteLine(DateTime.Now + " 執行操作"); } catch (Exception) { } }, null, 3000, Timeout.Infinite); Console.WriteLine(DateTime.Now + " 等待中..."); }
如果要實現定時執行的效果,就可以傳入period數值,dueTime如果傳入0的話,定時器就會在啟動后立刻執行一次
/// <summary> /// 立刻執行一次后每隔2秒執行一次 /// </summary> static void Test2() { Console.WriteLine(DateTime.Now + " 開始..."); Timer timer = new Timer((p) => { try { Console.WriteLine(DateTime.Now + " 執行操作"); } catch (Exception) { } }, null, 0, 2000); Console.WriteLine(DateTime.Now + " 等待中..."); }
定時執行很爽,但是如果業務代碼異常了或者是阻塞了,Test2依然會繼續循環調用,不斷的申請資源,一個處理不好,就很容易導致系統崩潰,那么有咩有什么辦法能讓Timer業務不執行完就不開始下一個任務呢,答案是可以的,就是利用Timer的Change函數來每次延遲執行
/// <summary> /// 每次延遲2秒執行,執行完畢后再延遲2秒 /// </summary> static void Test3() { Console.WriteLine(DateTime.Now + " 開始..."); Timer timer = null; timer = new Timer((arg) => { try { Console.WriteLine(DateTime.Now + " 延遲執行到了"); Thread.Sleep(3000); //模擬3秒的操作耗時 Console.WriteLine(DateTime.Now + " 執行操作"); } catch (Exception) { } finally { timer.Change(2000, Timeout.Infinite); //執行完3秒的操作后,再延遲2秒后執行 } }, null, 2000, Timeout.Infinite); //第一次延遲2秒執行 }
還有就是這個Timer不要像我這樣在方法中當作局部變量使用,因為資源緊張的時候GC有可能會把它給回收了,
Test1和Test3延遲執行不存在這個問題,但是Test2是循環執行就會出現這個問題,如果資源緊張,可能循環走着走着就沒了
所以用的時候一定要避免在方法中作為局部變量用,最好是把創建的Timer對象指向一個非局部變量