Last active
December 14, 2022 14:01
-
-
Save changhuixu/47ffb441575564b57e6446bb59466300 to your computer and use it in GitHub Desktop.
schedule cron job. IHostedService, asp.net core
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks for this! I found it very useful. The only modification I had to do was to support longer intervals, in my case monthly jobs. You can check out my changes here https://gist.github.com/dusan-tkac/2233fddc136b13ea656fe3d5bd9f1061