您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > .NET

.NET 6 新特性 PeriodicTimer

时间:2021-12-06 17:40:20  来源:  作者:IT狂人日记

Intro

.NET 6 中引入了一个新的 Timer ——
System.Threading.PeriodicTimer,和之前的几个 Timer 相比一个最大的区别就是,新的 PeriodicTimer 的事件处理可以比较方便地使用异步方式,消除了使用 callback 的机制,减少了使用的复杂度。

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 可以结合 CancellationToken 一起使用,和 CancellationToken 一起用的时候需要注意,如果 cancellationToken 被取消的时候会抛出一个
OperationCanceledException 需要考虑自己处理异常

除此之外如果 PeriodicTimer 被 Dispose,这个 timer 就相当于是失效的,并且无法重新恢复,来看下面这个示例:

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

上面这样的一段代码,在 WaitForNextTickAsync 之前就已经调用了 Dispose(),此时 WaitForNextTickAsync 方法会始终返回 false ,所以 Console.WriteLine 的逻辑也不会被执行

我们之前会尝试使用 Timer 来做一些后台任务,可以改造成使用新的 PeriodicTimer 来实现,小示例如下:

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

运行输出如下:

.NET 6 新特性 PeriodicTimer

 

More

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

  • 没有 callback 来绑定事件
  • 不会发生重入,只允许有一个消费者,不允许同一个 PeriodicTimer 在不同的地方同时 WaitForNextTickAsync,不需要自己做排他锁来实现不能重入
  • 异步化,之前的几个 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");
}

猜一下输出结果是什么,Timed event triggered 会输出几次

.NET 6 新特性 PeriodicTimer

 

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


Tags:.NET   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
编译和反编译.NET 中的编译是把开发人员写的 C# 代码转化为计算机可理解的代码的过程,也就是中间语言代码(IL代码)。在这个过程中,C# 源代码被转换为可执行文件(exe或者dll 文件)...【详细内容】
2022-07-15  Tags: .NET  点击:(1)  评论:(0)  加入收藏
我们在开发 webapi 项目时如果遇到 api 接口需要同时支持多个版本的时候,比如接口修改了入参之后但是又希望支持老版本的前端(这里的前端可能是网页,可能是app,小程序 等等)进行...【详细内容】
2022-07-14  Tags: .NET  点击:(3)  评论:(0)  加入收藏
什么是.NET.NET 是由 Microsoft 创建的开源开发平台,用于生成多种不同类型的应用程序,主要支持C#、F#及VB。.NET程序运行原理.NET程序的运行是由其虚拟机CLR(公共语言运行时)把...【详细内容】
2022-06-21  Tags: .NET  点击:(26)  评论:(0)  加入收藏
项目介绍一套基于.NetCore+Vue2/Vue3+Element plus+uniapp,采用前后端分离方式,全自动生成PC与移动端代码的快速开发脚手架;支持移动端(uniapp)ios/android/h5/微信小程序。 Vu...【详细内容】
2022-06-13  Tags: .NET  点击:(56)  评论:(0)  加入收藏
多年前借鉴b/s优势实现基于.net的c/s框架 本框架未采用.NET固有的WCF通讯解决方案,而使用传统http数据加密方式.框架初始和传统客户端升级方式一样检查新版本,如有则下载升级...【详细内容】
2022-06-05  Tags: .NET  点击:(30)  评论:(0)  加入收藏
Asp.Net Core Identity 是.Net自带的身份认证系统,支持用户界面 (UI) 登录功能,并且管理用户、密码、配置文件数据、角色、声明、令牌、电子邮件确认等等。使用Visual Studio...【详细内容】
2022-06-05  Tags: .NET  点击:(35)  评论:(0)  加入收藏
安装Hangfire新建ASP.NET Core空 项目,.Net Core版本3.1 往*.csproj添加包引用,添加新的PackageReference标记。如下所示。请注意,下面代码段中的版本可能已经过时,如有需要,请使...【详细内容】
2022-05-07  Tags: .NET  点击:(76)  评论:(0)  加入收藏
 B/S架构的Web程序几乎占据了应用软件的绝大多数市场,但是C/S架构的WinForm、WPF客户端程序依然具有很实用的价值,如设计类软件 AutoCAD与Autodesk Revit、WPS、IT类的集成开...【详细内容】
2022-04-27  Tags: .NET  点击:(153)  评论:(0)  加入收藏
前几天有个老项目找到我,有多老呢?比我工作年限都长,见到这个项目我还得叫一声前辈。这个项目目前使用非常稳定,十多年了没怎么更新过,现在客户想加一个小功能:在线预览Word文档。...【详细内容】
2022-04-27  Tags: .NET  点击:(65)  评论:(0)  加入收藏
之前,我们已经了解了ASP.NET Core中的身份认证,现在,我们来聊一下授权。老规矩,示例程序源码XXTk.Auth.Samples已经提交了,需要的请自取。概述ASP.NET Core中的授权方式有很多,我...【详细内容】
2022-04-20  Tags: .NET  点击:(143)  评论:(0)  加入收藏
▌简易百科推荐
编译和反编译.NET 中的编译是把开发人员写的 C# 代码转化为计算机可理解的代码的过程,也就是中间语言代码(IL代码)。在这个过程中,C# 源代码被转换为可执行文件(exe或者dll 文件)...【详细内容】
2022-07-15  IT狂人日记    Tags:.NET   点击:(1)  评论:(0)  加入收藏
我们在开发 webapi 项目时如果遇到 api 接口需要同时支持多个版本的时候,比如接口修改了入参之后但是又希望支持老版本的前端(这里的前端可能是网页,可能是app,小程序 等等)进行...【详细内容】
2022-07-14  IT技术资源爱好者    Tags:.Net   点击:(3)  评论:(0)  加入收藏
什么是.NET.NET 是由 Microsoft 创建的开源开发平台,用于生成多种不同类型的应用程序,主要支持C#、F#及VB。.NET程序运行原理.NET程序的运行是由其虚拟机CLR(公共语言运行时)把...【详细内容】
2022-06-21  威步上海    Tags:.NET   点击:(26)  评论:(0)  加入收藏
Asp.Net Core Identity 是.Net自带的身份认证系统,支持用户界面 (UI) 登录功能,并且管理用户、密码、配置文件数据、角色、声明、令牌、电子邮件确认等等。使用Visual Studio...【详细内容】
2022-06-05  海椰人  博客园  Tags:.Net   点击:(35)  评论:(0)  加入收藏
安装Hangfire新建ASP.NET Core空 项目,.Net Core版本3.1 往*.csproj添加包引用,添加新的PackageReference标记。如下所示。请注意,下面代码段中的版本可能已经过时,如有需要,请使...【详细内容】
2022-05-07  壮志林云    Tags:.NET   点击:(76)  评论:(0)  加入收藏
 B/S架构的Web程序几乎占据了应用软件的绝大多数市场,但是C/S架构的WinForm、WPF客户端程序依然具有很实用的价值,如设计类软件 AutoCAD与Autodesk Revit、WPS、IT类的集成开...【详细内容】
2022-04-27  IT技术资源爱好者  博客园  Tags:.NET   点击:(153)  评论:(0)  加入收藏
前几天有个老项目找到我,有多老呢?比我工作年限都长,见到这个项目我还得叫一声前辈。这个项目目前使用非常稳定,十多年了没怎么更新过,现在客户想加一个小功能:在线预览Word文档。...【详细内容】
2022-04-27  海椰人  博客园  Tags:.Net   点击:(65)  评论:(0)  加入收藏
之前,我们已经了解了ASP.NET Core中的身份认证,现在,我们来聊一下授权。老规矩,示例程序源码XXTk.Auth.Samples已经提交了,需要的请自取。概述ASP.NET Core中的授权方式有很多,我...【详细内容】
2022-04-20  日行四善  博客园  Tags:授权   点击:(143)  评论:(0)  加入收藏
序言本文将分别介绍 Authentication(认证) 和 Authorization(授权)。并以简单的例子在 ASP.NET Core 6.0 的 WebAPI 中分别实现这两个功能。 相关名词Authentication 和 Author...【详细内容】
2022-04-18  芦荟柚子茶  博客园  Tags:ASP.NET   点击:(197)  评论:(0)  加入收藏
前言由于客户网络安全限制,连接到互联网的设备不能访问内网。需要先从客户端应用中导出数据到文件,再将文件复制到U盘,最后通过内网机器上传数据。如何保证,在复制、传输过程中,...【详细内容】
2022-03-22  My IO    Tags:.NET Core   点击:(125)  评论:(0)  加入收藏
站内最新
站内热门
站内头条