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# 如何在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文件,然后按照下面的步骤操作 云

我想每年增加一班学生。我希望每年新年都自动执行此方法,

这是一个更具体系结构的问题,而不是编码问题。有几种方法可以实现这一点。Hangfire是其中最简单的:

一,

检查他们的文档以维护(编辑/删除/添加)定期作业

2.Ubuntu Cron作业

添加一个.net核心控制台应用程序,并将其设置为ubuntu服务器的cron作业

3.Windows服务任务计划程序

如果您使用windows server作为主机,您可以看到:

或者只是将你的.net内核转换成一个exe文件,然后按照下面的步骤操作

  • 云托管功能
  • 您可以使用Azure函数或Amazon lambda等云函数来运行定期/计划作业/任务

    请参阅我在本帖中的回复:

    如果要实现计划任务,我建议您也可以尝试使用包和配置计划任务(参考:)

    Cronos包是一个轻量级但功能齐全的库,用于解析cron表达式,并在考虑时区和夏令时的情况下计算下一次事件。Cronos是由HangfireIO赞助的开源项目,您可以从中阅读详细的文档。 具体步骤如下:

  • 通过NuGet安装软件包

  • 使用以下代码创建CronJobService服务:

    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();
    返回服务;
    }
    }
    
  • 创建ScheduleJob.cs:

     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);
    }
    }
    
  • 在ConfigureServices方法中注册ScheduleJob服务

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