86 lines
2.6 KiB
C#
86 lines
2.6 KiB
C#
using Cronos;
|
|
using Microsoft.Extensions.Hosting;
|
|
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Logging.Abstractions;
|
|
|
|
namespace ScheduledService;
|
|
|
|
public class CronJobService : IHostedService, IDisposable
|
|
{
|
|
private System.Timers.Timer? _timer;
|
|
private readonly CronExpression _expression;
|
|
private readonly TimeZoneInfo _timeZoneInfo;
|
|
private readonly ILogger<CronJobService> _logger;
|
|
|
|
public CronJobService(string cronExpression, TimeZoneInfo timeZoneInfo, ILogger<CronJobService>? logger = null)
|
|
{
|
|
_expression = CronExpression.Parse(cronExpression, CronFormat.IncludeSeconds);
|
|
_timeZoneInfo = timeZoneInfo;
|
|
_logger = logger ?? NullLogger<CronJobService>.Instance;
|
|
}
|
|
|
|
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)
|
|
{
|
|
await ScheduleJob(cancellationToken);
|
|
return;
|
|
}
|
|
|
|
_timer = new System.Timers.Timer(delay.TotalMilliseconds);
|
|
_timer.Elapsed += async (sender, args) =>
|
|
{
|
|
_timer?.Dispose();
|
|
_timer = null;
|
|
|
|
try
|
|
{
|
|
if (!cancellationToken.IsCancellationRequested)
|
|
await DoWork(cancellationToken);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "定时任务 DoWork 执行异常");
|
|
}
|
|
|
|
try
|
|
{
|
|
if (!cancellationToken.IsCancellationRequested)
|
|
await ScheduleJob(cancellationToken);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "定时任务 ScheduleJob 调度异常");
|
|
}
|
|
};
|
|
_timer.Start();
|
|
}
|
|
await Task.CompletedTask;
|
|
}
|
|
|
|
public virtual async Task DoWork(CancellationToken cancellationToken)
|
|
{
|
|
await Task.CompletedTask;
|
|
}
|
|
|
|
public virtual async Task StopAsync(CancellationToken cancellationToken)
|
|
{
|
|
_timer?.Stop();
|
|
await Task.CompletedTask;
|
|
}
|
|
|
|
public virtual void Dispose()
|
|
{
|
|
_timer?.Dispose();
|
|
}
|
|
}
|