<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          .NET 6 新特性 PeriodicTimer

          共 4404字,需瀏覽 9分鐘

           ·

          2021-12-10 10:39

          .NET 6 新特性 PeriodicTimer

          Intro

          .NET 6 中引入了一個新的 Timer —— ?System.Threading.PeriodicTimer,和之前的幾個 Timer 相比一個最大的區(qū)別就是,新的 PeriodicTimer 的事件處理可以比較方便地使用異步方式,消除了使用 callback 的機制,減少了使用的復(fù)雜度。

          Sample

          來看一個使用示例:

          using?var?cts?=?new?CancellationTokenSource();
          Console.CancelKeyPress?+=?(sender,?e)?=>
          {
          ????e.Cancel?=?true;
          ????cts.Cancel();
          };

          using?var?timer?=?new?PeriodicTimer(TimeSpan.FromSeconds(3));
          try
          {
          ????while?(await?timer.WaitForNextTickAsync(cts.Token))
          ????{
          ????????Console.WriteLine($"Timed?event?triggered({DateTime.Now:HH:mm:ss})");
          ????}
          }
          catch?(OperationCanceledException)
          {
          ????Console.WriteLine("Operation?cancelled");
          }

          通常 PeriodicTimer 可以結(jié)合 CancellationToken 一起使用,和 CancellationToken 一起用的時候需要注意,如果 cancellationToken 被取消的時候會拋出一個 OperationCanceledException 需要考慮自己處理異常

          除此之外如果 PeriodicTimerDispose,這個 timer 就相當(dāng)于是失效的,并且無法重新恢復(fù),來看下面這個示例:

          var?timer1?=?new?PeriodicTimer(TimeSpan.FromSeconds(2));
          timer1.Dispose();
          if?(await?timer1.WaitForNextTickAsync())
          {
          ????Console.WriteLine("Timer1?event?triggered");
          }

          上面這樣的一段代碼,在 WaitForNextTickAsync 之前就已經(jīng)調(diào)用了 Dispose(),此時 WaitForNextTickAsync 方法會始終返回 false ,所以 Console.WriteLine 的邏輯也不會被執(zhí)行

          我們之前會嘗試使用 Timer 來做一些后臺任務(wù),可以改造成使用新的 PeriodicTimer 來實現(xiàn),小示例如下:

          public?abstract?class?TimerScheduledService?:?BackgroundService
          {
          ????private?readonly?PeriodicTimer?_timer;
          ????private?readonly?TimeSpan?_period;
          ????protected?readonly?ILogger?Logger;

          ????protected?TimerScheduledService(TimeSpan?period,?ILogger?logger)
          ????{
          ????????Logger?=?logger;
          ????????_period?=?period;
          ????????_timer?=?new?PeriodicTimer(_period);
          ????}

          ????protected?override?async?Task?ExecuteAsync(CancellationToken?stoppingToken)
          ????{
          ????????try
          ????????{
          ????????????while?(await?_timer.WaitForNextTickAsync(stoppingToken))
          ????????????{
          ????????????????try
          ????????????????{
          ????????????????????Logger.LogInformation("Begin?execute?service");
          ????????????????????await?ExecuteInternal(stoppingToken);
          ????????????????}
          ????????????????catch?(Exception?ex)
          ????????????????{
          ????????????????????Logger.LogError(ex,?"Execute?exception");
          ????????????????}
          ????????????????finally
          ????????????????{
          ????????????????????Logger.LogInformation("Execute?finished");
          ????????????????}
          ????????????}
          ????????}
          ????????catch?(OperationCanceledException?operationCancelledException)
          ????????{
          ????????????Logger.LogWarning(operationCancelledException,?"service?stopped");
          ????????}
          ????}

          ????protected?abstract?Task?ExecuteInternal(CancellationToken?stoppingToken);

          ????public?override?Task?StopAsync(CancellationToken?cancellationToken)
          ????{
          ????????Logger.LogInformation("Service?is?stopping.");
          ????????_timer.Dispose();
          ????????return?base.StopAsync(cancellationToken);
          ????}
          }

          實現(xiàn)示例如下:

          public?class?TimedHealthCheckService?:?TimerScheduledService
          {
          ????public?TimedHealthCheckService(ILogger?logger)?:?base(TimeSpan.FromSeconds(5),?logger)
          ????{
          ????}

          ????protected?override?Task?ExecuteInternal(CancellationToken?stoppingToken)
          ????{
          ????????Logger.LogInformation("Executing...");
          ????????return?Task.CompletedTask;
          ????}
          }

          運行輸出如下:

          logging output

          More

          新的 PeriodicTimer 相比之前的幾個 Timer 來說,有下面幾個特點

          • 沒有 callback 來綁定事件
          • 不會發(fā)生重入,只允許有一個消費者,不允許同一個 PeriodicTimer 在不同的地方同時 WaitForNextTickAsync,不需要自己做排他鎖來實現(xiàn)不能重入
          • 異步化,之前的幾個 timer 的 callback 都是同步的,使用新的 timer 我們可以更好的使用異步方法,避免寫 Sync over Async 之類的代碼
          • Dispose() 之后,該實例就無法再使用,WaitForNextTickAsync 始終返回 false

          最后來做一個題目,把第一個示例改造一下,最終代碼如下:

          using?var?cts?=?new?CancellationTokenSource();
          cts.CancelAfter(TimeSpan.FromSeconds(30));
          using?var?timer?=?new?PeriodicTimer(TimeSpan.FromSeconds(3));
          try
          {
          ????while?(await?timer.WaitForNextTickAsync(cts.Token))
          ????{
          ????????await?Task.Delay(5000);
          ????????Console.WriteLine($"Timed?event?triggered({DateTime.Now:HH:mm:ss})");
          ????}
          }
          catch?(OperationCanceledException)
          {
          ????Console.WriteLine("Operation?cancelled");
          }

          猜一下輸出結(jié)果是什么,Timed event triggered 會輸出幾次








          References

          • https://www.ilkayilknur.com/a-new-modern-timer-api-in-dotnet-6-periodictimer
          • https://docs.microsoft.com/en-us/dotnet/api/system.threading.periodictimer?view=net-6.0
          • https://github.com/dotnet/runtime/blob/v6.0.0/src/libraries/System.Private.CoreLib/src/System/Threading/PeriodicTimer.cs
          • https://github.com/dotnet/runtime/issues/31525
          • https://github.com/WeihanLi/SamplesInPractice/blob/master/net6sample/PeriodicTimerSample/Program.cs
          • https://github.com/OpenReservation/ReservationServer/blob/dev/OpenReservation.Helper/Services/CronScheduleServiceBase.cs#L91


          瀏覽 61
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲豆花视频 | 北条麻妃AV在线 | 黄色一级视频免费领 | 大香蕉伊人操 | 亚洲日韩一级精品片在线观看 |