2017年1月10日

Timer 執行完前次工作後再倒數

這裡用的Timer是System.Threading.Timer;

目的是在倒數計時的程式中,不要前一次工作還沒完成,下一次工作就開始執行。

看到兩種作法

  1. 用Thread中的Monitor去鎖定物件來做控制
  2. 改變計時器時間(這個比較準)
第一種作法是在function中加上Multi thread 中 Monitor的機制,程式範例如下
主要是第6行和17行



    1 private void run(object state)
    2 {
    3         var objs = state as KeyValuePair<object, List<DbSync>>?;
    4         if (objs == null || !objs.HasValue) return;
    5
    6         if (Monitor.TryEnter(objs.Value.Key))
    7         {
    8                 try
    9                 {
   10                         foreach (var syncObj in objs.Value.Value)
   11                         {
   12                                 syncObj.Run();
   13                         }
   14                 }
   15                 finally
   16                 {
   17                         Monitor.Exit(objs.Value.Key);
   18                 }
   19         }
   20 }


第二種作法是在Timer的建構子中傳入Delegate function,在function裡面作本來要作的工作,完成後改變timer的時間;timer設置好就執行,但一開始將下一次執行的時間設為無限大,接下來是執行完後改成再過x(=30sec)時間後執行,每次的下次執行時間是在delegate function重設所以"下次執行時間"都設為無限大,範例如下:


    1 TTimer timer = null;
    2 timer = new TTimer((p) =>
    3 {
    4         run(task.Value);
    5         timer.Change(30 * 1000, Timeout.Infinite);
    6 }, null, 0, Timeout.Infinite);



結論:假設interval設為30秒
  • 第一種可以達到我的目的,但倒數時間不準確,如果工作執行長一點,兩次的間隔不會是30秒,可能十幾秒就執行下一次了(應該是執行的時候,計時器還是在偷倒數,然後不知道是被卡在那裡,過才繼續重算…)。
  • 第二種ok,間隔差不多就是30秒(因為測試function中亂睡覺,所以我也不知道是不是超精確 XD);另外這這種作法因為直接寫了delegate function,在裡面作工作,所以本來要執行的function不用被限制只傳object進去function中,可以傳其他型態,這樣可以少轉一次型,不錯。







沒有留言: