C# 如何在ASP.NET核心应用程序中使用BackgroundService每年执行一个方法? 公共异步任务DoWork(CancellationToken CancellationToken) { var scope=serviceScopeFactory.CreateScope(); var context=scope.ServiceProvider.GetService(); 而(!cancellationToken.IsCancellationRequested) { foreach(context.Students.ToList()中的var x) { x、 Class++; 情境。学生。更新(x); } SaveChanges(); 等待任务。延迟(1000); } }
我想每年增加一班学生。我希望每年新年都自动执行此方法,这是一个更具体系结构的问题,而不是编码问题。有几种方法可以实现这一点。Hangfire是其中最简单的: 一, 检查他们的文档以维护(编辑/删除/添加)定期作业 2.Ubuntu Cron作业 添加一个.net核心控制台应用程序,并将其设置为ubuntu服务器的cron作业 3.Windows服务任务计划程序 如果您使用windows server作为主机,您可以看到: 或者只是将你的.net内核转换成一个exe文件,然后按照下面的步骤操作C# 如何在ASP.NET核心应用程序中使用BackgroundService每年执行一个方法? 公共异步任务DoWork(CancellationToken CancellationToken) { var scope=serviceScopeFactory.CreateScope(); var context=scope.ServiceProvider.GetService(); 而(!cancellationToken.IsCancellationRequested) { foreach(context.Students.ToList()中的var x) { x、 Class++; 情境。学生。更新(x); } SaveChanges(); 等待任务。延迟(1000); } },c#,.net,asp.net-core,background-service,C#,.net,Asp.net Core,Background Service,我想每年增加一班学生。我希望每年新年都自动执行此方法,这是一个更具体系结构的问题,而不是编码问题。有几种方法可以实现这一点。Hangfire是其中最简单的: 一, 检查他们的文档以维护(编辑/删除/添加)定期作业 2.Ubuntu Cron作业 添加一个.net核心控制台应用程序,并将其设置为ubuntu服务器的cron作业 3.Windows服务任务计划程序 如果您使用windows server作为主机,您可以看到: 或者只是将你的.net内核转换成一个exe文件,然后按照下面的步骤操作 云
请参阅我在本帖中的回复: 如果要实现计划任务,我建议您也可以尝试使用包和配置计划任务(参考:) Cronos包是一个轻量级但功能齐全的库,用于解析cron表达式,并在考虑时区和夏令时的情况下计算下一次事件。Cronos是由HangfireIO赞助的开源项目,您可以从中阅读详细的文档。 具体步骤如下:
RecurringJob.AddOrUpdate(() =>{
foreach(var x in context.Students.ToList()) {
x.Class++;
context.Students.Update(x);
}
context.SaveChanges();
},
Cron.Yearly);
公共抽象类CronJobService:IHostedService,IDisposable
{
专用系统.Timers.Timer\u定时器;
私有只读CronExpression\u表达式;
私有只读TimeZoneInfo_TimeZoneInfo;
受保护的CronJobService(字符串cronExpression,TimeZoneInfo TimeZoneInfo)
{
_expression=CronExpression.Parse(CronExpression);
_timeZoneInfo=timeZoneInfo;
}
公共虚拟异步任务StartAsync(CancellationToken CancellationToken)
{
等待ScheduleJob(取消令牌);
}
受保护的虚拟异步任务调度作业(CancellationToken CancellationToken)
{
var next=_expression.GetNextOccurrence(DateTimeOffset.Now,_timeZoneInfo);
if(next.HasValue)
{
var delay=next.Value-DateTimeOffset.Now;
if(delay.totalms
{
_timer.Dispose();//重置和释放计时器
_定时器=空;
如果(!cancellationToken.IsCancellationRequested)
{
等待工作(取消令牌);
}
如果(!cancellationToken.IsCancellationRequested)
{
等待ScheduleJob(cancellationToken);//重新安排下一步
}
};
_timer.Start();
}
等待任务。完成任务;
}
公共虚拟异步任务DoWork(CancellationToken CancellationToken)
{
等待任务。延迟(5000,取消令牌);//完成工作
}
公共虚拟异步任务StopAsync(CancellationToken CancellationToken)
{
_计时器?.Stop();
等待任务。完成任务;
}
公共虚拟void Dispose()
{
_计时器?.Dispose();
}
}
公共接口IsScheduleConfig
{
字符串表达式{get;set;}
TimeZoneInfo TimeZoneInfo{get;set;}
}
公共类ScheduleConfig:isScheduleConfig
{
公共字符串表达式{get;set;}
公共时区信息TimeZoneInfo{get;set;}
}
公共静态类ScheduledServiceExtensions
{
公共静态IServiceCollection AddCronJob(此IServiceCollection服务,操作选项),其中T:CronJobService
{
如果(选项==null)
{
抛出新ArgumentNullException(nameof(options),@“请提供计划配置”);
}
var config=new ScheduleConfig();
options.Invoke(config);
if(string.IsNullOrWhiteSpace(config.CronExpression))
{
抛出新ArgumentNullException(nameof(ScheduleConfig.CronExpression),@“不允许使用空的Cron表达式”);
}
services.AddSingleton(config);
services.AddHostedService();
返回服务;
}
}
public abstract class CronJobService : IHostedService, IDisposable
{
private System.Timers.Timer _timer;
private readonly CronExpression _expression;
private readonly TimeZoneInfo _timeZoneInfo;
protected CronJobService(string cronExpression, TimeZoneInfo timeZoneInfo)
{
_expression = CronExpression.Parse(cronExpression);
_timeZoneInfo = timeZoneInfo;
}
public virtual async Task StartAsync(CancellationToken cancellationToken)
{
await ScheduleJob(cancellationToken);
}
protected virtual async Task ScheduleJob(CancellationToken cancellationToken)
{
var next = _expression.GetNextOccurrence(DateTimeOffset.Now, _timeZoneInfo);
if (next.HasValue)
{
var delay = next.Value - DateTimeOffset.Now;
if (delay.TotalMilliseconds <= 0) // prevent non-positive values from being passed into Timer
{
await ScheduleJob(cancellationToken);
}
_timer = new System.Timers.Timer(delay.TotalMilliseconds);
_timer.Elapsed += async (sender, args) =>
{
_timer.Dispose(); // reset and dispose timer
_timer = null;
if (!cancellationToken.IsCancellationRequested)
{
await DoWork(cancellationToken);
}
if (!cancellationToken.IsCancellationRequested)
{
await ScheduleJob(cancellationToken); // reschedule next
}
};
_timer.Start();
}
await Task.CompletedTask;
}
public virtual async Task DoWork(CancellationToken cancellationToken)
{
await Task.Delay(5000, cancellationToken); // do the work
}
public virtual async Task StopAsync(CancellationToken cancellationToken)
{
_timer?.Stop();
await Task.CompletedTask;
}
public virtual void Dispose()
{
_timer?.Dispose();
}
}
public interface IScheduleConfig<T>
{
string CronExpression { get; set; }
TimeZoneInfo TimeZoneInfo { get; set; }
}
public class ScheduleConfig<T> : IScheduleConfig<T>
{
public string CronExpression { get; set; }
public TimeZoneInfo TimeZoneInfo { get; set; }
}
public static class ScheduledServiceExtensions
{
public static IServiceCollection AddCronJob<T>(this IServiceCollection services, Action<IScheduleConfig<T>> options) where T : CronJobService
{
if (options == null)
{
throw new ArgumentNullException(nameof(options), @"Please provide Schedule Configurations.");
}
var config = new ScheduleConfig<T>();
options.Invoke(config);
if (string.IsNullOrWhiteSpace(config.CronExpression))
{
throw new ArgumentNullException(nameof(ScheduleConfig<T>.CronExpression), @"Empty Cron Expression is not allowed.");
}
services.AddSingleton<IScheduleConfig<T>>(config);
services.AddHostedService<T>();
return services;
}
}
公共类ScheduleJob:CronJobService
{
专用只读ILogger\u记录器;
公共ScheduleJob(isScheduleConfig配置,ILogger记录器)
:base(config.CronExpression,config.TimeZoneInfo)
{
_记录器=记录器;
}
公共覆盖任务StartAsync(CancellationToken CancellationToken)
{
_logger.LogInformation(“ScheduleJob启动”);
返回base.StartAsync(cancellationToken);
}
公共覆盖任务DoWork(CancellationToken CancellationToken)
{
_logger.LogInformation($“{DateTime.Now:hh:mm:ss}ScheduleJob正在工作。”);
返回Task.CompletedTask;
}
公共覆盖任务StopAsync(CancellationToken CancellationToken)
{
_logger.LogInformation(“ScheduleJob正在停止”);
返回base.StopAsync(cancellationToken);
}
}
public class ScheduleJob: CronJobService
{
private readonly ILogger<ScheduleJob> _logger;
public ScheduleJob(IScheduleConfig<ScheduleJob> config, ILogger<ScheduleJob> logger)
: base(config.CronExpression, config.TimeZoneInfo)
{
_logger = logger;
}
public override Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("ScheduleJob starts.");
return base.StartAsync(cancellationToken);
}
public override Task DoWork(CancellationToken cancellationToken)
{
_logger.LogInformation($"{DateTime.Now:hh:mm:ss} ScheduleJob is working.");
return Task.CompletedTask;
}
public override Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("ScheduleJob is stopping.");
return base.StopAsync(cancellationToken);
}
}
<
public class ScheduleJob: CronJobService
{
private readonly ILogger<ScheduleJob> _logger;
public ScheduleJob(IScheduleConfig<ScheduleJob> config, ILogger<ScheduleJob> logger)
: base(config.CronExpression, config.TimeZoneInfo)
{
_logger = logger;
}
public override Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("ScheduleJob starts.");
return base.StartAsync(cancellationToken);
}
public override Task DoWork(CancellationToken cancellationToken)
{
_logger.LogInformation($"{DateTime.Now:hh:mm:ss} ScheduleJob is working.");
return Task.CompletedTask;
}
public override Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("ScheduleJob is stopping.");
return base.StopAsync(cancellationToken);
}
}
public void ConfigureServices(IServiceCollection services)
{
services.AddHostedService<HelloWorldHostedService>();
services.AddCronJob<ScheduleJob>(c=>
{
c.TimeZoneInfo = TimeZoneInfo.Local;
c.CronExpression = @"25 21 * * *"; // 21:25 PM daily.
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}