定时器_在.net core3.0 webapi中添加自定义定时器功能

原文:定时器_在.net core3.0 webapi中添加自定义定时器功能

  前言:想在.net framework环境使用自定义定时器的话,参考我的另一篇文章:https://www.cnblogs.com/lxhbky/p/10242839.html

  想在.net core中使用定时器功能,需要借助一个服务接口:IHostedService,   继承并实现对应方法,最后再setup.cs类中添加注册服务:services.AddHostedService<实现服务类>();   既然要写计时器的服务器,那么该实现类就要包含定时器,本篇博客也是借助System.Timers.Timer类封装的。

  下面展示具体代码:

  1-公用基类:

  

public class ModelBase
    {
        protected IServiceProvider Services { get; set; }
        protected IWebHostEnvironment WebHostEnvironment { get; set; }
        /// <summary>
        /// 配置帮助类
        /// </summary>
        protected ConfigHelper ConfigHelper { get; set; }
        /// <summary>
        /// 等同于ASP.NET里面的WebCache(HttpRuntime.Cache)
        /// </summary>
        protected IMemoryCache MemoryCache { get; set; }

        /// <summary>
        /// 日志
        /// </summary>
        protected ILogger Logger { get; set; }

        /// <summary>
        /// 授权帮助
        /// </summary>
        protected OAuthHelper OAuthHelper { get; set; }

        /// <summary>
        /// HttpClient帮助工厂
        /// </summary>
        protected IHttpClientFactory HttpClientFactory { get; set; }

        public ModelBase(params object[] @params)
        {
            foreach (var item in @params)
            {
                if (item is IServiceProvider)
                {
                    this.Services = (IServiceProvider)item;
                }
                else if (item is IWebHostEnvironment)
                {
                    this.WebHostEnvironment = (IWebHostEnvironment)item;
                }
                else if (item is ConfigHelper)
                {
                    this.ConfigHelper = (ConfigHelper)item;
                }
                else if (item is IMemoryCache)
                {
                    this.MemoryCache = (IMemoryCache)item;
                }
                else if (item is ILogger)
                {
                    this.Logger = (ILogger)item;
                }
                else if (item is OAuthHelper)
                {
                    this.OAuthHelper = (OAuthHelper)item;
                }
                else if (item is IHttpClientFactory)
                {
                    this.HttpClientFactory = (IHttpClientFactory)item;
                }

            }

        }
    }

  

  2-计时器封装类:

  相对于.net framework文章计时器部分的类做了对应优化,更加简化了:

using Microsoft.Extensions.Logging;
using PaymentAccountAPI.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Timers;

namespace PaymentAccountAPI.Helper
{
    /// <summary>
    /// 定时周期帮助类
    /// </summary>
    public class TimeCycleHelp : ModelBase
    {
        public TimeCycleHelp(ILogger<TimeCycleHelp> logger) : base(logger)
        {
            this.Timer = new System.Timers.Timer();
        }

        /// <summary>
        /// 服务专属计时器
        /// </summary>
        private System.Timers.Timer Timer;

        /// <summary>
        /// 默认计时器时间间隔1秒(提高计时器开始时间准确度)
        /// </summary>
        private double DefaultTimerInterval = 1 * 1000;

        /// <summary>
        /// 设置多个循环周期
        /// </summary>
        private List<TimeCycle> TimeCycleList { get; set; }

        /// <summary>
        /// 更新一个计时器的计时周期
        /// </summary>
        /// <param name="newTimerInterval">新的计时周期</param>
        /// <param name="isFirstStart">是否是首次更新计时器周期</param>
        private void UpdateTimeInterval(double newTimerInterval, bool isFirstStart = false)
        {
            if (this.Timer != null && newTimerInterval > 0)
            {
                this.Timer.Stop();
                if (this.Timer.Interval != newTimerInterval)
                {
                    this.Timer.Interval = newTimerInterval;
                }
                if (isFirstStart)
                {
                    this.Timer.Elapsed += new System.Timers.ElapsedEventHandler(this.ServiceAction);
                }
                this.Timer.AutoReset = true;
                this.Timer.Start();
            }
        }

        /// <summary>
        /// 内部辅助方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ServiceAction(object sender, ElapsedEventArgs e)
        {
            List<TimeCycle> currentTimeCycleList = new List<TimeCycle>(0);

            DateTime now = DateTime.Now;
            DateTime cycleBeginTime;
            DateTime cycleEndTime;
            foreach (TimeCycle timeCycle in this.TimeCycleList)
            {
                cycleBeginTime = Convert.ToDateTime(timeCycle.BeginTime);
                cycleBeginTime = now.Date.AddHours(cycleBeginTime.Hour).AddMinutes(cycleBeginTime.Minute).AddSeconds(cycleBeginTime.Second);
                cycleEndTime = Convert.ToDateTime(timeCycle.EndTime);
                cycleEndTime = now.Date.AddHours(cycleEndTime.Hour).AddMinutes(cycleEndTime.Minute).AddSeconds(cycleEndTime.Second);
                if (cycleEndTime < cycleBeginTime)
                {
                    cycleEndTime = cycleEndTime.AddDays(1);
                }

                if (now >= cycleBeginTime && now <= cycleEndTime)
                {
                    //有最大执行次数限制或者没有限制
                    if (timeCycle.ActionExecutionTimes < timeCycle.MaxActionTimes || timeCycle.MaxActionTimes == 0)
                    {
                        TimeSpan timeSpan = now - cycleBeginTime;
                        bool isCanAction = (int)timeSpan.TotalSeconds % timeCycle.ActionSeconds == 0 ? true : false;
                        if (isCanAction)
                        {
                            timeCycle.ActionExecutionTimes++;
                            currentTimeCycleList.Add(timeCycle);
                        }
                    }
                }
                else
                {
                    //不在计时周期内,已执行次数清零
                    timeCycle.ActionExecutionTimes = 0;
                }
            }
            //找到当前循环周期后,执行周期内动作
            if (currentTimeCycleList.Count > 0)
            {
                currentTimeCycleList.ForEach(item =>
                {
                    //使用多线程执行任务,让代码快速执行
                    Task.Run(() => item.Action());
                });
            }
        }

        /// <summary>
        /// 开启计时器
        /// </summary>
        /// <param name="timeCycleArray"></param>
        public void Start(params TimeCycle[] timeCycleArray)
        {
            if (timeCycleArray != null && timeCycleArray.Length > 0)
            {
                if (this.TimeCycleList == null)
                {
                    this.TimeCycleList = new List<TimeCycle>(100);
                }
                this.TimeCycleList = timeCycleArray.ToList();

                //设置首次计时器周期(首次动作执行,是在计时器启动后在设置的时间间隔后做出的动作)
                this.UpdateTimeInterval(this.DefaultTimerInterval, true);
            }
        }

        /// <summary>
        /// 结束计时器
        /// </summary>
        public void Stop()
        {
            this.Timer.Stop();
        }

    }

    /// <summary>
    /// 计时周期类
    /// </summary>
    public class TimeCycle
    {
        /// <summary>
        /// 唯一标识
        /// </summary>
        public int ID { get; set; }
        /// <summary>
        /// 开始时间(误差1秒=取决于计时器默认时间间隔)
        /// </summary>
        public string BeginTime { get; set; }
        /// <summary>
        /// 结束时间
        /// </summary>
        public string EndTime { get; set; }
        /// <summary>
        /// 最大执行次数
        /// </summary>
        public int MaxActionTimes { get; set; }
        /// <summary>
        /// 计时周期内执行的动作(动作会在到达开始时间后的)
        /// </summary>
        public Action Action { get; set; }
        /// <summary>
        /// 动作执行时间间隔(秒)
        /// </summary>
        public int ActionSeconds { get; set; }
        /// <summary>
        /// 方法执行次数
        /// </summary>
        internal int ActionExecutionTimes { get; set; }

        public TimeCycle(int id, Action action, int actionSeconds) : this(id, "00:00:00", action, actionSeconds)
        {
        }

        public TimeCycle(int id, string beginTime, Action action, int actionSeconds) : this(id, beginTime, action, actionSeconds, 0)
        {
        }

        public TimeCycle(int id, string beginTime, Action action, int actionSeconds, int maxActionTimes) : this(id, beginTime, "23:59:59", action, actionSeconds, maxActionTimes)
        {
        }

        /// <summary>
        /// 基本构造器
        /// </summary>
        /// <param name="id">唯一标识</param>
        /// <param name="beginTime">开始时间</param>
        /// <param name="endTime">结束时间</param>
        /// <param name="action">要执行的任务</param>
        /// <param name="actionSeconds">任务执行时间间隔</param>
        /// <param name="maxActionTimes">最大执行次数</param>
        public TimeCycle(int id, string beginTime, string endTime, Action action, int actionSeconds, int maxActionTimes)
        {
            this.ID = id;
            this.BeginTime = beginTime;
            this.EndTime = endTime;
            this.Action = action;
            this.ActionSeconds = actionSeconds;
            this.MaxActionTimes = maxActionTimes;
        }
    }
}

  3-webAPI服务封装类:

  

using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using PaymentAccountAPI.Common;
using PaymentAccountAPI.Helper;
using PaymentAccountAPI.PaymentAccountHelper;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace PaymentAccountAPI.Hangfire
{
    public class SyncToCMSService : ModelBase, IHostedService
    {private TimeCycleHelp _TimeCycleHelp { get; set; }

        public SyncToCMSService(ConfigHelper configHelper,
                                TimeCycleHelp timeCycleHelp, ILogger<SyncToCMSService> logger) : base(logger, configHelper)
        {this._TimeCycleHelp = timeCycleHelp;
        }

        public void SyncData()
        {
           //...需要执行的任务代码

            this.Logger.LogInformation($"定时任务:完成{currentDate.ToShortDateString()}的交易记录同步!");
        }

        public Task StartAsync(CancellationToken cancellationToken)
        {
            this.Logger.LogInformation($"定时任务:同步服务已启动...");

            //正式代码
            string syncBeginTime = this.ConfigHelper.GetAppSettingValue("SyncCMSBeginTime");
            string syncEndTime = this.ConfigHelper.GetAppSettingValue("SyncCMSEndTime");
            this._TimeCycleHelp.Start(new TimeCycle(999, syncBeginTime, syncEndTime, this.SyncData, 3600, 2));

            //测试代码
            //this._TimeCycleHelp.Start(new TimeCycle(999, "12:00:00", () =>
            //{
            //    this.Logger.LogInformation("test123");
            //}, 10, 3));

            return Task.CompletedTask;
        }

        public Task StopAsync(CancellationToken cancellationToken)
        {
            this.Logger.LogInformation($"同步服务已停止...");
            this._TimeCycleHelp.Stop();

            return Task.CompletedTask;
        }

    }
}

  4-在startup.cs添加注册服务:

  

            #region 添加定时任务

            services.AddSingleton<TimeCycleHelp>();

            services.AddHostedService<SyncToCMSService>();

            #endregion

  最后感谢一篇道友的文章:.Net Core 简单定时任务框架封装

原文地址:https://www.cnblogs.com/lonelyxmas/p/12239113.html

时间: 2024-09-30 14:32:23

定时器_在.net core3.0 webapi中添加自定义定时器功能的相关文章

ASP.NET Core 3.0 WebApi中使用Swagger生成API文档简介

参考地址,官网:https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/getting-started-with-swashbuckle?view=aspnetcore-2.2&tabs=visual-studio 与https://www.jianshu.com/p/349e130e40d5 当一个WebApi完成之后,书写API文档是一件非常头疼的事,因为不仅要写得清楚,能让调用接口的人看懂,又是非常耗时耗力的一件事.在之前的一篇随笔中(

第十四篇:在SOUI中使用定时器

前言 定时器是win32编程中常用的制作动画效果的手段.在Win32编程中,可以使用::SetTimer来创建定时器,定时器消息会被会发到调用SetTimer时指定的HWND. 在SOUI中一般来说只有一个宿主窗口有HWND,所有的SWindow都属于一个宿主窗口,如此一来直接使用::SetTimer创建的定时器就难以直接分发到SWindow对象了. 在SOUI的控件中使用定时器 为了能够方便的在SWindow中使用定时器,在SOUI系统中,我们通过将定时器ID(共32位)按位进行分解: cla

.Net Core 3.0后台使用httpclient请求网络网页和图片_使用Core3.0做一个简单的代理服务器

原文:.Net Core 3.0后台使用httpclient请求网络网页和图片_使用Core3.0做一个简单的代理服务器 目标:使用.net core最新的3.0版本,借助httpclient和本机的host域名代理,实现网络请求转发和内容获取,最终显示到目标客户端! 背景:本人在core领域是个新手,对core的使用不多,因此在实现的过程中遇到了很多坑,在这边博客中,逐一介绍下.下面进入正文 正文: 1-启用httpClient注入: 参考文档:https://docs.microsoft.c

.net WebApi中使用swagger生成WepApi集成测试工具

我在WebApi中使用swagger的时候发现会出现很多问题,搜索很多地方都没找到完全解决问题的方法,后面自己解决了,希望对于遇到同样问题朋友有帮助.我将先一步一步的演示项目中解决swagger遇到问题及解决方法. 首先我们新建一个api项目 图1 (默认生成项目) 图2(运行首页) 图3(默认Api列表) 图4(默认Get的Api) 以上图1-4都是默认情况下生成页面看起来不是那么好看,而且测试也不方便,下面将介绍怎么使用swagger. 使用nuget包获取Swashbule.swagger

MFC的DLL中实现定时器功能

方法一:创建一个线程, 反复读系统时间不就可以了? 如果定时要求不严,用Sleep就可以了.DWORD WINAPI TimerThread(LPVOID pamaram) { UINT oldTickCount, newTickCount; oldTickCount = GetTickCount(); //获取的是毫秒数 while(TRUE) { while(TRUE) { newTickCount = GetTickCount(); // 获取的是毫秒数 if(newTickCount -

Qt中使用定时器(可使用QObject::timerEvent定时执行,QTimer::singleShot可只触发一次)

在Qt中使用定时器有两种方法,一种是使用QObiect类的定时器:一种是使用QTimer类.定时器的精确性依赖于操作系统和硬件,大多数平台支持20ms的精确度 1.QObject类的定时器 QObject是所有Qt对象的基类,它提供了一个基本的定时器.通过QObject::startTimer(),可以把一个一毫秒为单位的时间间隔作为参数来开始定时器,这个函数返回一个唯一的整数定时器的标识符.这个定时器开始就会在每一个时间间隔"触发",直到明确的使用这个定时器的标识符来调用QObjec

Java中的定时器

注意:内容来自网络他人文章,特此声明 一.Java中的定时器 在JAVA中实现定时器功能要用的2个重要类是 Timer类:定时器类,需要一个TimerTask类的实例作为参数: TimerTask:定时器任务类,定时器要执行的任务在该类的run方法中定义. 二.实现定时器的两种写法 1.普通实现(相对于通过内部类来实现而言) 1 //先写一个类 2 public class TimeTest { 3 public static void main(String[] args) { 4 5 Tim

JavaScript中的定时器

定时器 1.setTimeout 这个方法用于在指定的毫秒数之后执行某个函数,返回定时器的句柄 混合的 setTimeout()方法设置一个定时器,该定时器在定时器到期后执行一个函数或指定的一段代码. 语法 let timeoutID = window.setTimeout(func[, delay, param1, param2, ...]); let timeoutID = scope.setTimeout(code[, delay]); let timeoutID = window.set

net WebApi中使用swagger

net WebApi中使用swagger 我在WebApi中使用swagger的时候发现会出现很多问题,搜索很多地方都没找到完全解决问题的方法,后面自己解决了,希望对于遇到同样问题朋友有帮助.我将先一步一步的演示项目中解决swagger遇到问题及解决方法. 首先我们新建一个api项目 图1 (默认生成项目) 图2(运行首页) 图3(默认Api列表) 图4(默认Get的Api) 以上图1-4都是默认情况下生成页面看起来不是那么好看,而且测试也不方便,下面将介绍怎么使用swagger. 使用nuge