netcore 后台任务 指定每天某一时间执行任务
简单的实现每天运行一次的定时器,执行时间放在数据库为了用户能方便随意修改。
一、使用System.Threading.Timer
实现方式,通过backgroundService后台任务,放入每1小时查看数据库中的时间一次,如果执行时间正好在1小时之内,就使用System.Threading.Timer执行一次任务。
1、在Startup.cs注册两个服务
services.AddScoped<AutoSubmitApplicationService>();
services.AddHostedService<BackgroundApplySubmitService>();
2、BackgroundApplySubmitService
public class BackgroundApplySubmitService : BackgroundService { private readonly ILogger<BackgroundApplySubmitService> _logger; private readonly AutoSubmitApplicationService _applictionService; private Timer _timer; public BackgroundApplySubmitService(ILogger<BackgroundApplySubmitService> logger, IServiceScopeFactory factory) { _logger = logger; _applictionService = factory.CreateScope().ServiceProvider.GetRequiredService<AutoSubmitApplicationService>(); ; } protected override Task ExecuteAsync(CancellationToken stoppingToken) {
//每一小时执行一次 _timer = new Timer(_applictionService.GetTimeOfApplictionSubmit, null, 10000,3600000); return Task.CompletedTask; } public override void Dispose() { base.Dispose(); _timer?.Dispose(); } }
3、AutoSubmitApplicationService
public class AutoSubmitApplicationService { private readonly DataContext db; private readonly ILogger<AutoSubmitApplicationService> _logger; public AutoSubmitApplicationService(DataContext dbContext, ILogger<AutoSubmitApplicationService> logger) { _logger = logger; db = dbContext; } public void GetTimeOfApplictionSubmit(object o) { var item = db.SetAutoApplication.FirstOrDefault(); var isStartUp = item?.IsStartUp ?? false; var gotoTime = item?.GotoTime ?? ""; if (isStartUp && Regex.IsMatch(gotoTime, @"^\d{2}:\d{2}$")) { var arrtime = gotoTime.Split(":").Select(x => Convert.ToDouble(x)).ToArray(); var h = arrtime[0]; var m = arrtime[1]; DateTime oneOClick = DateTime.Today.AddHours(h).AddMinutes(m); DateTime now = DateTime.Now; var due = (int)((oneOClick - now).TotalMilliseconds); Console.WriteLine(due); if ((due >= 0 && due <= 3600000)) { //在一个小时内执行任务 var task = new System.Threading.Timer(DoWord); task.Change(due, 0); } } } private void DoWord(object o) { Console.WriteLine("一天只执行一次"); } }
实现完毕
二、使用
System.Timers.Timer
public class BackgroundApplySubmitService : BackgroundService { private readonly ILogger<BackgroundApplySubmitService> _logger; private readonly AutoSubmitApplicationService _applictionService; private readonly IServiceScopeFactory _factory; private Timer timer; private System.Timers.Timer doworkTimer; private DataContext db; private string intervaltime; private static int i=0; public BackgroundApplySubmitService(ILogger<BackgroundApplySubmitService> logger, IServiceScopeFactory factory) { _logger = logger; _factory = factory; _applictionService = _factory.CreateScope().ServiceProvider.GetRequiredService<AutoSubmitApplicationService>(); } protected override Task ExecuteAsync(CancellationToken stoppingToken) { intervaltime = "01:00";//默认一小时 Console.WriteLine("定时器启动"); //每1分钟执行一次 timer = new Timer(MyIntervalometer, null, 1000, 1000);
//开始就执行一次 StartupTime(); return Task.CompletedTask; } public void MyIntervalometer(object o) { Console.WriteLine(++i); //从数据库中取间隔 string db_intervaltime = ""; using (var scope = _factory.CreateScope()) { db = scope.ServiceProvider.GetRequiredService<DataContext>(); db_intervaltime = db.SetAutoApplication.First().intervalTime; } if (db_intervaltime != intervaltime) { i = 0; doworkTimer?.Stop(); intervaltime = db_intervaltime; StartupTime(); } } /// <summary> /// /// </summary> /// <param name="time">格式:分:秒 (01:30)</param> public void StartupTime() { Console.WriteLine($"间隔运行时间:{intervaltime}"); var item = intervaltime.Split(":").Select(x => Convert.ToInt32(x)).ToArray(); var interval = (item[0]*60+item[1]) * 1000; doworkTimer =new System.Timers.Timer(); doworkTimer.Interval = interval; doworkTimer.AutoReset = true; doworkTimer.Enabled = true; doworkTimer.Elapsed += DoworkTimer_Elapsed; } private void DoworkTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { Console.WriteLine("间隔时间后执行一次"); } public override void Dispose() { base.Dispose(); timer?.Dispose(); doworkTimer?.Stop(); doworkTimer?.Dispose(); } }
三、直接一点,每分钟运行一次去判断
timer = new Timer(task, null, 1000, 60000);
task
public void MyTimer(object o) { var item = db.SetAutoApplication.FirstOrDefault(); if (item != null) { var isStartUp = item.IsStartUp; var gotoTime = item.GotoTime; if (isStartUp && Regex.IsMatch(gotoTime, @"^\d{2}:\d{2}$")) { var hm = gotoTime.Split(":").Select(x => Convert.ToInt32(x)).ToArray(); var now = DateTime.Now; if (now.Hour == hm[0] && now.Minute == hm[1]) { DoWord(); } } } }