在 ASP.NET Core 3.1 中,如何在未来的特定日期和时间安排带有托管服务的后台任务(Cron 作业)? [英] In ASP.NET Core 3.1, how can I schedule a background task (Cron Jobs) with hosted services for a specific date and time in the future?
问题描述
我正在开发一个基于 ASP.NET Core 3.1 的项目,我想向它添加一个特定的功能,以安排将来在帖子作者指定的日期和时间发布帖子(类似于 Wordpress 为通过其 cron 作业安排的帖子).例如,如果我们从用户那里收到这个日期和时间:
I am working on a project based on ASP.NET Core 3.1 and I want to add a specific functionality to it to schedule publishing a post in the future in a date and time specified by post author (something like what Wordpress does for scheduled posts through its cron jobs). For example, if we receive this date and time from user :
2020-09-07 14:08:07
那么,如何通过使用托管服务仅运行一次并更改数据库中的标志并在此之后保存更改来为其安排后台任务?
Then, how can I schedule a background task for it by using hosted services to run only for one time and to change a flag in database and save changes after that?
我读过一些关于它的文章,但他们没有指定日期和时间,只是提到了每 5 秒重复一次的任务以及类似 cron 表达式的东西,但是,我需要知道的是我如何为特定日期和时间安排后台任务?
I've read some articles about it but they didn't specify date and time and just mentioned repeated tasks for every 5 second and stuff like that with cron expressions, but, the thing I need to know is how can I schedule a background task for a specific date and time?
提前致谢.
推荐答案
经过反复试验,我找到了一种方法,可以按照我的要求使用托管服务为特定日期和时间安排后台任务在这个问题中,我用 System.Threading.Timer
和 Timespan
这样做了:
After some trial and error I found a way to schedule a background task for specific date and time by using hosted service as I asked in the question, and, I did that with System.Threading.Timer
and Timespan
like this:
public class ScheduleTask : IScheduler, IDisposable
{
private Timer _timer;
private IBackgroundTaskQueue TaskQueue { get; }
// Set task to schedule for a specific date and time
public async Task SetAndQueueTaskAsync(ScheduleTypeEnum scheduleType, DateTime scheduleFor, Guid scheduledItemId)
{
// Omitted for simplicity
// ....
TaskQueue.QueueBackgroundWorkItem(SetTimer);
}
// ......
// lines omitted for simplicity
// .....
// Set timer for schedule item
private Task SetTimer(CancellationToken stoppingToken)
{
// ......
// lines omitted for simplicity
// .....
_timer = new Timer(DoWork, null, (item.ScheduledFor - DateTime.UtcNow).Duration(), TimeSpan.Zero);
return Task.CompletedTask;
}
private void DoWork(object state)
{
ScheduledItemChangeState(DateTime.UtcNow).Wait();
}
// Changes after the scheduled time comes
private async Task ScheduledItemChangeState(DateTime scheduleFor)
{
using (var scope = Services.CreateScope())
{
var context =
scope.ServiceProvider
.GetRequiredService<DataContext>();
// Changing some data in database
}
}
public void Dispose()
{
_timer?.Dispose();
}
}
如果你看看上面代码中我通过 (item.ScheduledFor - DateTime.UtcNow)
作为 Timer 类构造函数的第三个参数来初始化它的一个新实例的部分,我实际上是问在我存储为 item.ScheduledFor
中的 DateTime 的特定时间执行特定工作的计时器.
If you look at the part of the above code in which I passed (item.ScheduledFor - DateTime.UtcNow)
as Timer class constructor's third parameter to initialize a new instance of it, I actually ask the timer to do a specific work in a specific time I stored as a DateTime in item.ScheduledFor
.
您可以在此处从 Microsoft 官方文档中阅读有关 ASP.NET Core 中托管服务的后台任务的更多信息:
You could read more about background tasks with hosted services in ASP.NET Core here from official Microsoft docs:
要查看我的 Github 存储库中的完整实现,它可以在重新启动服务器后从数据库中恢复计划任务,请使用以下链接:
To see the full implementation in my Github repo which has the possibility to recover the scheduled tasks from database after restarting the server, use the following link:
https://github.com/aspian-io/aspian/tree/master/Infrastructure/Schedule
这篇关于在 ASP.NET Core 3.1 中,如何在未来的特定日期和时间安排带有托管服务的后台任务(Cron 作业)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!