如何在 ASP.NET 核心应用程序中使用 BackgroundService 每年执行一个方法?

如何解决如何在 ASP.NET 核心应用程序中使用 BackgroundService 每年执行一个方法?

     public async Task DoWork(CancellationToken cancellationToken)
         { 
             var scope = serviceScopeFactory.CreateScope();
             var context = scope.ServiceProvider.GetService<ApplicationDbContext>();
             while (!cancellationToken.IsCancellationRequested)
                {
                  foreach(var x in context.Students.ToList())
                  {
                   x.Class ++;
                   context.Students.Update(x);
                  } 
                     context.SaveChanges();
                     await Task.Delay(1000);
                 }
        }

我想每年增加 1 个学生的班级。我想每年新年自动执行这个方法

解决方法

这是一个更具架构性的问题,而不是编码问题。有几种方法可以实现这一点。 Hangfire是其中最容易的:

1.Hangfire

RecurringJob.AddOrUpdate(() =>{
  foreach(var x in context.Students.ToList()) {
    x.Class++;
    context.Students.Update(x);
  }
  context.SaveChanges();
},Cron.Yearly);

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

2.Ubuntu Cron 作业

添加 .net 核心控制台应用程序并将其设置为 ubuntu 服务器的 cron 作业 https://ermir.net/topic-2/execute-net-core-console-application-as-an-ubuntu-cron-job

3.Windows 服务任务计划程序

如果您使用 Windows 服务器作为主机,您可以看到:https://medium.com/better-programming/asp-net-core-windows-service-task-scheduler-daily-weekly-monthly-700a569d502a

或者只是将您的 .net 核心制作成一个 exe 文件并按照此 https://superuser.com/questions/239427/setting-an-annual-task-on-windows-task-scheduler?rq=1

  1. 云托管功能

您可以使用 Azure 函数或 Amazon lambda 等云函数来运行重复/计划作业/任务 https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-scheduled-function https://docs.aws.amazon.com/lambda/latest/dg/services-cloudwatchevents-tutorial.html

,

请参考我在此线程中的回复: How to trigger .NET Core 3.1 Hosted Service at certain time?

如果你想实现定时任务,我建议你也可以尝试使用Cronos包和Cron Expressions来配置定时任务(参考:link) .

Cronos 包是一个轻量级但功能齐全的库,用于解析 cron 表达式并计算下一次出现的时区和夏令时。 Cronos 是一个由 HangfireIO 赞助的开源项目,您可以从 its GitHub repository 阅读详细的文档。 详细步骤如下:

  1. 通过 NuGet 安装 Cronos 包。

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

     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;
         }
     }
    
  3. 创建一个 ScheduleJob.cs:

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

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

    然后结果如下:

    enter image description here

在上面的示例中,它将在每天晚上 21:25 运行调度作业。您可以将 CronExpression 更改为 0 0 1 1 *,然后,该作业将在每年 1 月 1 日午夜运行一次。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?