關於週期性執行的子執行緒有幾個要點:
- 單次 Sleep 的時間不要太久,會影響程式的關閉
- 不可以用 SpinWait 來做程式暫停,要用 Sleep 來暫停,這樣才會釋放 CPU
- Error log 要注意會重複出現相同的 error
- 有排除重複 error 時,要記得加上[錯誤解除]的 log,這樣才能知道程式是否有回到正常執行
- 要執行的程式邏輯移到一個 method 裡,這樣可以避免 return 造成的迴圈中斷,也能分離邏輯的關注點
週期小於 10 秒的範本
private static readonly ILogger _log = LogManager.GetCurrentClassLogger(); private int _cycleMSec = 1000; private bool _runFlag = false; private string _prevError; public void Start() { if (_runFlag) { return; } _runFlag = true; var thread = new Thread(() => { while (_runFlag) { /* 先睡可以避免在程式啟動時過於忙碌 */ Thread.Sleep(_cycleMSec); try { /* 要執行的程式邏輯 */ cycleHandler(); if (_prevError != null) { _log.Info("錯誤結束"); } _prevError = null; } catch (Exception ex) { /* 避免相同的錯誤一直被記錄 */ if (_prevError == ex.Message) { continue; } _prevError = ex.Message; _log.Fatal(ex, "執行錯誤"); } } }); thread.Start(); } public void Stop() { _runFlag = false; } private void cycleHandler() { // 主要的邏輯程式寫在這裡 }
週期大於 10 秒的範本
private static readonly ILogger _log = LogManager.GetCurrentClassLogger(); private int _cycleSec = 30; private bool _runFlag = false; private string _prevError; private DateTime _nextTime = DateTime.Now; public void Start() { if (_runFlag) { return; } _runFlag = true; var thread = new Thread(() => { while (_runFlag) { /* 先睡可以避免在程式啟動時過於忙碌 */ Thread.Sleep(1000); /* 檢查是否符合執行時間 */ if (_nextTime > DateTime.Now) { continue; } /* 更新下一次的執行時間 */ _nextTime = DateTime.Now.AddSeconds(_cycleSec); try { /* 要執行的程式邏輯 */ cycleHandler(); if (_prevError != null) { _log.Info("錯誤結束"); } _prevError = null; } catch (Exception ex) { /* 避免相同的錯誤一直被記錄 */ if (_prevError == ex.Message) { continue; } _prevError = ex.Message; _log.Fatal(ex, "執行錯誤"); } } }); thread.Start(); } public void Stop() { _runFlag = false; } private void cycleHandler() { // 主要的邏輯程式寫在這裡 }
停啟頻繁的範本
public enum CycleStatus { Stop, Start, Stoping, } public CycleStatus RunStatus { get; private set; } = CycleStatus.Stop; private static readonly ILogger _log = LogManager.GetCurrentClassLogger(); private int _cycleMSec = 1000; private string _prevError; public void Start() { if (RunStatus != CycleStatus.Stop) { throw new Exception("程序還在進行中"); } RunStatus = CycleStatus.Start; var thread = new Thread(() => { while (RunStatus == CycleStatus.Start) { /* 先睡可以避免在程式啟動時過於忙碌 */ Thread.Sleep(_cycleMSec); try { /* 要執行的程式邏輯 */ cycleHandler(); if (_prevError != null) { _log.Info("錯誤結束"); } _prevError = null; } catch (Exception ex) { /* 避免相同的錯誤一直被記錄 */ if (_prevError == ex.Message) { continue; } _prevError = ex.Message; _log.Fatal(ex, "執行錯誤"); } } RunStatus = CycleStatus.Stop; }); thread.Start(); } public void Stop() { if (RunStatus == CycleStatus.Stop) { throw new Exception("程序已經停止"); } if (RunStatus == CycleStatus.Stoping) { throw new Exception("程序正在停止"); } RunStatus = CycleStatus.Stoping; } private void cycleHandler() { // 主要的邏輯程式寫在這裡 }
0 回應:
張貼留言