Search code examples
c#asp.net-core.net-corecronasp.net-core-mvc

Cron expression: run task once per-day in ASP.Net Core


My asp.net core program needs to collect all the IP which access the website pre-day.

I need to output the IP list to a txt file when a day is over.

Therefore, the program should run a method to save the IP list once per-day.

How should I design it?

In my opinion, I will add a looping task in the startup.cs and set the Task.Delay to 24 hours(one day).

Should I do it like this? Thank you.


Solution

  • This is how I implement scheduler task in ASP.Net Core. Please note that you have to know how to use cron epxression.

    First add this package in your csproj

    <PackageReference Include="ncrontab" Version="3.3.1" />
    

    Next I will create SceduledProcessor.cs

    public abstract class ScheduledProcessor : ScopedProcessor
        {
            private readonly CrontabSchedule _schedule;
            private DateTime _nextRun;
    
            protected ScheduledProcessor(IServiceScopeFactory serviceScopeFactory) : base(serviceScopeFactory)
            {
                _schedule = CrontabSchedule.Parse(GetCronExpression(serviceScopeFactory));
                _nextRun = _schedule.GetNextOccurrence(DateTime.Now);
            }
    
            protected override async Task ExecuteAsync(CancellationToken stoppingToken)
            {
                do
                {
                    var now = DateTime.Now;
                    _schedule.GetNextOccurrence(now);
    
                    if (now > _nextRun)
                    {
                        await ProcessBackgroundTask();
                        _nextRun = _schedule.GetNextOccurrence(DateTime.Now);
                    }
    
                    await Task.Delay(5000, stoppingToken);
                }
                while (!stoppingToken.IsCancellationRequested);
            }
    
            protected abstract string GetCronExpression(IServiceScopeFactory serviceScopeFactory);
        }
    

    The ExecuteAsync will be run for our scenario

    Please note that we have to implement GetCronExpression method

    Next I will implement the service class

    public class ScheduledEmailService : ScheduledProcessor
        {
            public ScheduledEmailService(
                IServiceScopeFactory serviceScopeFactory) : base(serviceScopeFactory)
            {
            }
    
            /// <summary>
            /// Get cron setting from db
            /// </summary>
            /// <returns></returns>
            protected override string GetCronExpression(IServiceScopeFactory serviceScopeFactory)
            {
                return ""; // return your cron expression here you can get from db or static string
            }
    
            public override Task ProcessInScope(IServiceProvider serviceProvider)
            {
                // do something you wish
                return Task.CompletedTask;
            }
        }
    

    Bonus here I small class with predefined value for cron expression you can use it

    public static class CronExpression
        {
            public static readonly string EveryMinute = "0 * * * * *";
            public static readonly string EveryDay = "0 0 0 * * *";
            public static readonly string EveryWeek = "0 0 * * 0";
            public static readonly string EveryWeekend = "0 0 0 * * 6,0";
        }
    

    Finally add this to your Startup.cs

    services.AddSingleton<IHostedService, ScheduledEmailService>();