每天午夜在 .Net Core 3.0 中运行后台服务



我想每天午夜运行后台服务.NET Core默认后台服务在task.delay上运行,我想每午夜(24小时间隔(运行一次。

我的问题是后台服务在每个task.Delay间隔上运行,而不是指定的特定时间。

public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
private readonly IServiceScopeFactory _serviceScopeFactory;
public Worker(ILogger<Worker> logger, IServiceScopeFactory serviceScopeFactory)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_serviceScopeFactory = serviceScopeFactory ?? throw new ArgumentNullException(nameof(serviceScopeFactory));
}
protected override async Task ExecuteAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
// We ultimately resolve the actual services we use from the scope we create below.
// This ensures that all services that were registered with services.AddScoped<T>()
// will be disposed at the end of the service scope (the current iteration).
using var scope = _serviceScopeFactory.CreateScope();
var configuration = scope.ServiceProvider.GetRequiredService<IWorkFlowScheduleService>();
configuration.DailySchedule(dateTime: DateTime.Now);
_logger.LogInformation($"Sending message to ");
await Task.Delay(TimeSpan.FromSeconds(10), cancellationToken);
}
}
}

这是我的解决方案。

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
do
{
int hourSpan = 24 - DateTime.Now.Hour;
int numberOfHours = hourSpan;
if (hourSpan == 24)
{
//do something
numberOfHours = 24;
}
await Task.Delay(TimeSpan.FromHours(numberOfHours), stoppingToken);
}
while (!stoppingToken.IsCancellationRequested);
}

放一个等到午夜的初始Task.Delay,做你需要做的任何事情,然后Task.Delay24 小时怎么样?

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
// calculate seconds till midnight
var now = DateTime.Now;
var hours = 23 - now.Hour;
var minutes = 59 - now.Minute;
var seconds = 59 - now.Second;
var secondsTillMidnight = hours * 3600 + minutes * 60 + seconds;
// wait till midnight
await Task.Delay(TimeSpan.FromSeconds(secondsTillMidnight), stoppingToken);
while (!stoppingToken.IsCancellationRequested)
{
// do stuff
_logger.LogInformation($"Sending message to ");
// wait 24 hours
await Task.Delay(TimeSpan.FromHours(24), stoppingToken);
}
}

这是另一种可能的解决方案。

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
do
{
var waitTime = new TimeSpan(23, 59, 59) - DateTime.Now.TimeOfDay;
await Task.Delay(waitTime, stoppingToken);
//Do Work
} while (!cancellationToken.IsCancellationRequested);
}

我使用 NCrontab 3.3.1

https://www.nuget.org/packages/ncrontab/

这样,你可以使用 cron;否则,我同意前面的评论之一,即创建一个控制台应用程序并直接在您的服务器上将其作为 cron 或服务运行。

下面是我如何实现 NCrontab 的示例。

public class YourServiceName : BackgroundService
{
private CrontabSchedule _schedule;
private DateTime _nextRun;
// My CrontabHelper class simply returns a string representing a cron schedule. You can just use 0 0 0 * * * to run every day at midnight instead
private string Schedule => CrontabHelper.Schedule(CrontabHelper.CronType.Day); 
public YourServiceName()
{
_schedule = CrontabSchedule.Parse(Schedule, new CrontabSchedule.ParseOptions { IncludingSeconds = true });
_nextRun = _schedule.GetNextOccurrence(DateTime.Now);
}
protected async override Task ExecuteAsync(CancellationToken stoppingToken)
{
do
{
var now = DateTime.Now;
if (now > _nextRun)
{
// DO WORK HERE
}
await Task.Delay(5000, stoppingToken);
}
while (!stoppingToken.IsCancellationRequested);
}
}

然后在您的程序中.cs包括以下内容

builder.Services.AddHostedService<YourServiceName>();

希望这有帮助!

最新更新