關於週期性執行的子執行緒有幾個要點:
- 單次 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 回應:
張貼留言