首页 > 其他分享 >.NET 6 新东西 --PeriodicTimer

.NET 6 新东西 --PeriodicTimer

时间:2023-11-29 19:23:41浏览次数:36  
标签:CancellationToken -- Dispose timer WaitForNextTickAsync PeriodicTimer NET Logger

在.NET 6 中引入了新 Timer:System.Threading.PeriodicTimer,它和之前的 Timer 相比,最大的区别就是新的 PeriodicTimer 事件处理可以方便地使用异步,消除使用 callback 机制减少使用复杂度。讲解 PeriodicTimer 之前我们先来看以下该怎么使用它:

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($"触发事件({DateTime.Now:HH:mm:ss})");
    }
}
catch (OperationCanceledException e)
{
    Console.WriteLine("出现异常,运行停止"+e.Message);
}

一般来说 PeriodicTimer 会结合 CancellationToken 来使用,需要注意的是当 CancellationToken 被取消时会抛出 OperationCanceledException 异常,因此需要手动处理异常。另外当 PeriodicTimer 被 Dispose 掉时,这个 timer 就失效且无法恢复,我们来看下面这个示例:

var timer1 = new PeriodicTimer(TimeSpan.FromSeconds(10));
timer1.Dispose();
if (await timer1.WaitForNextTickAsync())
{
    Console.WriteLine("事件执行");
}

上面的代码中在 WaitForNextTickAsync 之前就已经调用了 Dispose(),这时 WaitForNextTickAsync 方法就只能返回 false,因此后续的代码将不会被执行。在以前的.NET 版本中我们会使用 Timer 来做后台任务,那么在.NET6 中我们同样可以这么做,官方示例代码如下:

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);
    }
}

public class TimedHealthCheckService : TimerScheduledService
{
    public TimedHealthCheckService(ILogger<TimedHealthCheckService> logger) : base(TimeSpan.FromSeconds(5), logger)
    {
    }
    protected override Task ExecuteInternal(CancellationToken stoppingToken)
    {
        Logger.LogInformation("Executing...");
        return Task.CompletedTask;
    }
}

总结

PeriodicTimer 相比之前的 Timer 来说,有下面几个特点: 

  1. 没有 callback 来绑定事件;

  2. 不会发生重入,只允许有一个消费者,不允许同一个 PeriodicTimer 在不同的地方同时 WaitForNextTickAsync,不需要自己做排他锁来实现不能重入;

  3. 异步化。之前的 timer 的 callback 都是同步的,使用新 timer 可以使用异步方法,避免了编写 Sync over Async 代码;

  4. Dispose 之后,实例就无法使用,并且 WaitForNextTickAsync 始终返回 false。

标签:CancellationToken,--,Dispose,timer,WaitForNextTickAsync,PeriodicTimer,NET,Logger
From: https://www.cnblogs.com/lgx5/p/17865644.html

相关文章

  • luogu2839题解
    [国家集训队]middle题目分析代码如下。#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;typedefunsignedlonglongull;constintMAXN=2e4+10;intx,n,Q,a[MAXN],q[6],root[MAXN],b[MAXN],tot;vector<int>locp[MAXN];structSegmentTreeNode{......
  • Servlet - 使用 changeSessionId() 改变SessionId 防止会话固定攻击
    Servlet-使用changeSessionId()改变SessionId防止会话固定攻击在会话固定攻击,黑客获取/设置(通过任何方式)另一个人的会话ID。然后,黑客可以冒充他人并获取敏感信息。JavaServlet3.1引入了以下HttpServletRequest方法:StringchangeSessionId()此方法将当前会话id更......
  • 解决主机与虚拟机之间无法复制粘贴的问题办法
    1.卸载VMwareToolssudoapt-getautoremoveopen-vm-tools2.联网安装VMwaretoolssudoapt-getinstallopen-vm-tools-desktop3.记得要重启虚拟机!ps:重启后,使用ctrlc+v似乎还是不能复制粘贴,也不能通过拖动文件来复制,但是可以通过鼠标右键复制粘贴文本或者文件,也算解......
  • C# 泛型编译特性对性能的影响
    C#作为一种强类型语言,具有丰富的泛型支持,允许开发者编写可以应对不同数据类型的通用代码。然而,在泛型编译时,针对结构和类作为泛型参数时,会对性能产生不同的影响。泛型编译行为在C#中,泛型编译行为取决于泛型参数的类型。具体而言,当泛型参数是结构(Struct)时,编译器会针对每个具体的......
  • java 令牌解析_SpringSecurity 原理解析【4】:令牌还原与Session String changeSessio
    java令牌解析_SpringSecurity原理解析【4】:令牌还原与SessionStringchangeSessionId();//修改SessionIdSpringSecurity原理解析【4】:令牌还原与SessionSession:一般称为会话,不同环境中含义不同,在SpringSecurity中一个会话指:客户端从令牌认证请求到登出注销请求之间的......
  • IIS 10的重大更新通常会随着Windows Server和Windows 10的累积更新一起发布,这些更新可
    IIS10是WindowsServer 和Windows10操作系统中内置的Web服务器角色。针对IIS10的重大更新通常会随着WindowsServer和Windows10的累积更新一起发布,这些更新可能包括性能改进、安全性增强、新功能和修复程序。在过去的更新中,IIS10可能会获得以下方面的重大改进:安全性增......
  • FPGA 实现SPI 主机双工通信 CS前后肩可调 操作时钟频率可调 ,SPI模式可调,传输位宽可
    1//testbench2`timescale1ns/1ns3modulelcd_spi_m_tb();4regrst_n_i;5regspi_clkx_i;6reg[31:0]spi_data_i;7regspi_start;8regspi_miso_r1,spi_miso_r2;9wirespi_miso_i;10wire[0:0]spi_done;11wir......
  • VSCode - Disable go test cache
    or Adding"-count=1"to"go.testFlags"candisablegotestcache.......
  • 小惊喜继续-vscode插件小更新:基于文件名中的 PostId 关联博文
    在惊喜小现:园子的vscode插件的预热博文发布后,今天发布插件的一个小更新——基于文件名中包含的PostId关联博文。将本地文件与服务端博文进行关联是通过插件在vscode中管理博文的基础,当您在插件的“随便列表”中点击一篇博文,会自动在工作空间的目录中创建以博文标题命名的文......
  • 深入了解HMAC加密技术:原理、应用与实践
    一、引言在网络安全领域,消息认证码(MAC)是一种重要的技术手段。Hash-basedMessageAuthenticationCode(HMAC)作为其中的一种,凭借其简单、高效、安全的特性,广泛应用于各种网络通信场景。本文将详细介绍HMAC的原理、应用与实践,帮助读者深入了解这一技术。HMAC在线加密--一个覆盖......