定时器_在.net core3.0 webapi中添加自定义定时器功能
标签:简单 exe turn single sse lis url def handle
前言:想在.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; }
///
/// 配置帮助类
///
protected ConfigHelper ConfigHelper { get; set; }
///
/// 等同于ASP.NET里面的WebCache(HttpRuntime.Cache)
///
protected IMemoryCache MemoryCache { get; set; }
///
/// 日志
///
protected ILogger Logger { get; set; }
///
/// 授权帮助
///
protected OAuthHelper OAuthHelper { get; set; }
///
/// HttpClient帮助工厂
///
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
{
///
/// 定时周期帮助类
///
public class TimeCycleHelp : ModelBase
{
public TimeCycleHelp(ILogger logger) : base(logger)
{
this.Timer = new System.Timers.Timer();
}
///
/// 服务专属计时器
///
private System.Timers.Timer Timer;
///
/// 默认计时器时间间隔1秒(提高计时器开始时间准确度)
///
private double DefaultTimerInterval = 1 * 1000;
///
/// 设置多个循环周期
///
private List TimeCycleList { get; set; }
///
/// 更新一个计时器的计时周期
///
/// 新的计时周期
/// 是否是首次更新计时器周期
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();
}
}
///
/// 内部辅助方法
///
///
///
private void ServiceAction(object sender, ElapsedEventArgs e)
{
List currentTimeCycleList = new List(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 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());
});
}
}
///
/// 开启计时器
///
///
public void Start(params TimeCycle[] timeCycleArray)
{
if (timeCycleArray != null && timeCycleArray.Length > 0)
{
if (this.TimeCycleList == null)
{
this.TimeCycleList = new List(100);
}
this.TimeCycleList = timeCycleArray.ToList();
//设置首次计时器周期(首次动作执行,是在计时器启动后在设置的时间间隔后做出的动作)
this.UpdateTimeInterval(this.DefaultTimerInterval, true);
}
}
///
/// 结束计时器
///
public void Stop()
{
this.Timer.Stop();
}
}
///
/// 计时周期类
///
public class TimeCycle
{
///
/// 唯一标识
///
public int ID { get; set; }
///
/// 开始时间(误差1秒=取决于计时器默认时间间隔)
///
public string BeginTime { get; set; }
///
/// 结束时间
///
public string EndTime { get; set; }
///
/// 最大执行次数
///
public int MaxActionTimes { get; set; }
///
/// 计时周期内执行的动作(动作会在到达开始时间后的)
///
public Action Action { get; set; }
///
/// 动作执行时间间隔(秒)
///
public int ActionSeconds { get; set; }
///
/// 方法执行次数
///
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)
{
}
///
/// 基本构造器
///
/// 唯一标识
/// 开始时间
/// 结束时间
/// 要执行的任务
/// 任务执行时间间隔
/// 最大执行次数
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 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();
services.AddHostedService();
#endregion
最后感谢一篇道友的文章:.Net Core 简单定时任务框架封装
定时器_在.net core3.0 webapi中添加自定义定时器功能
标签:简单 exe turn single sse lis url def handle
原文地址:https://www.cnblogs.com/lxhbky/p/12218988.html
评论