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

I want to increase class of student By 1 every year. I want to execute this method automatically every new year,

MADMAX
  • 152
  • 1
  • 3
  • 17
  • in which kind of server you want to host this? – Syed Mohammad Fahim Abrar Feb 01 '21 at 05:16
  • Coravel task scheduler is easy to use and get started with. It uses .NET Core hosted services under the covers, so no need to install anything other than the package. Since it's .NET native, not a port from an existing library for .NET Framework, it hooks into DI, etc: https://github.com/jamesmh/coravel – Majid Shahabfar Feb 01 '21 at 05:26
  • Hi @zombie551, Whether the reply has solved the problem or is there any update about this thread? If you have any question about my reply, please let me know freely. If the answer resolved the issue, kindly accept it - see [What should I do when someone answers my question](https://stackoverflow.com/help/someone-answers). – Zhi Lv Feb 09 '21 at 09:22

2 Answers2

1

This is a more architectural question rather than a coding question. There are several ways to achieve this. Hangfire is the easiest among them:

1.Hangfire

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

check their documentation to maintain(edit/delete/add) recurring jobs

2.Ubuntu Cron Job

Add a .net core console app and set it as a cron job of your ubuntu server https://ermir.net/topic-2/execute-net-core-console-application-as-an-ubuntu-cron-job

3.Windows Service Task Scheduler

If you are using windows server as hosting you can see this : https://medium.com/better-programming/asp-net-core-windows-service-task-scheduler-daily-weekly-monthly-700a569d502a

or just make your .net core to an exe file and follow this https://superuser.com/questions/239427/setting-an-annual-task-on-windows-task-scheduler?rq=1

  1. Cloud hosted functions

You can use cloud functions such like Azure functions or Amazon lambda to run recurring/scheduled jobs/tasks https://learn.microsoft.com/en-us/azure/azure-functions/functions-create-scheduled-function https://docs.aws.amazon.com/lambda/latest/dg/services-cloudwatchevents-tutorial.html

keipala
  • 768
  • 2
  • 7
  • 19
1

Please refer to my reply in this thread: How to trigger .NET Core 3.1 Hosted Service at certain time?

If you want to implement scheduled tasks, I suggest you could also try to use the Cronos package and the Cron Expressions to configure the scheduled task (reference: link).

The Cronos package is a lightweight but full-fledged library for parsing cron expressions and calculating next occurrences with time zones and daylight saving time in mind. The Cronos is an open source project sponsored by HangfireIO, and you can read detailed documentation from its GitHub repository. The details steps as below:

  1. Install the Cronos package via NuGet.

  2. Create a CronJobService service with the following code:

     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. create a 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. Register the ScheduleJob service in the ConfigureServices method.

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

    Then the result as below:

    enter image description here

In the above sample, it will run the Schedule Job at 21:25 PM daily. You can change the CronExpression to 0 0 1 1 *, then, the job will run once a year at midnight of 1 January.

Zhi Lv
  • 18,845
  • 1
  • 19
  • 30