问题描述
在某些情况下,我需要在特定时间(在我的ASP .NET Core项目中)执行某些代码。
我知道延迟任务不是一个很好的解决方案,但这就是我所拥有的,我想知道如何使其工作:
async Task MyMethod()
{
// do something
// Create a new thread that waits for the appropriate time
TimeSpan time = dbAppointment.ScheduledOn - TimeSpan.FromMinutes(5.0) - DateTime.UtcNow;
_ = Task.Delay(time).ContinueWith(async x => await
notificationmanager.CreateReminder());
// continue doing something
}
public async Task CreateReminder() {}
但是在尝试使用我通过DI注入到dbContext
构造函数中的notificationmanager
时失败,说明它已被废弃。
这是依赖项的“流程”:
public class MyClass
{
private readonly MyContext dbContext;
private readonly Inotificationmanager notificationmanager;
public MyClass(MyContext context,Inotificationmanager nm)
{
dbContext = context;
notificationmanager = nm;
}
public async Task MyMethod() // the method shown in the snippet above
{
// method does something using the dbContext
_ = Task.Delay(time).ContinueWith(async x => await
notificationmanager.CreateReminder());
}
}
public class notificationmanager: Inotificationmanager
{
private readonly MyContext dbContext;
public notificationmanager(MyContext context) { dbContext = context;}
public async Task CreateReminder() { // this method uses the dbContext}
}
startup.cs中的DI设置:
services.AddDbContext<MyContext>();
services.AddScoped<Inotificationmanager,notificationmanager>();
解决方法
选项
- 使用作业调度程序(例如Hangfire,Quartz.Net,Jobbr,...)
- 如果您的.net核心版本为> = 2,请使用background service
在两种情况下,都需要在作业类中注入DatabaseContext,否则将收到ObjectDisposedException。
当您需要横向扩展到多台计算机时,您将需要具有状态存储的作业服务器,例如SQL Server,MSMQ,RabbitMQ,Redis等。
使用Hangfire进行采样
public class MyDelayJob
{
private readonly MyContext dbContext;
private readonly INotificationManager notificationManager;
public MyDelayJob(MyContext context,INotificationManager nm)
{
dbContext= context;
notificationManager = nm;
}
public async Task Run(/*parameters*/)
{
await notificationManager.CreateReminder()
}
}
/*Shedule code in MyMethod
IBackgroundJobClient can be injected
you need to register MyDelayJob with your IOC container.
*/
backgroundJobClient.Schedule<MyDelayJob>(j => j.Run(),TimeSpan.FromSeconds(60))
请参阅IBackgroundJobClient的文档