我正在尝试在ASP.Net Core 1.1中的Web应用程序上实现cron任务。
我决定选择Hangfire库。
为了检查我的安装和配置是否正常工作,我只写了一个非常简单的定期作业,旨在在控制台输出上打印当前的DateTime:
RecurringJob.AddOrUpdate(() => Console.WriteLine($"{DateTime.Now}"), Cron.Minutely);
奇怪的是,它每分钟打印相同的消息,对应于第一次打印消息的日期和时间,而不是更新DateTime.Now
部分。
如果我访问/ Hangfire仪表板,并查看作业详细信息,它将显示为静态日期时间输出,如下所示:
Console.WriteLine("15/09/2017 15:27:21");
所以这项工作在入队时似乎有点“编译”,这显然不是我打算做的。
我尝试通过计算数据库表中的行的作业来替换此作业。问题是一样的:如果我在作业的两次出现之间添加或删除行,则不会更新显示的行数。仅当我重新启动Web应用程序时才会进行更新。
答案 0 :(得分:1)
所以你的问题是Hangfire使用NewtonSoft序列化你发送给作业的参数。当你的程序将作业排入队列时,它将获得当前时间,然后将在该时间内调用该函数。
尝试将该函数移动到方法调用中。而不是
RecurringJob.AddOrUpdate(() => Console.WriteLine($"{DateTime.Now}"), Cron.Minutely);
尝试
RecurringJob.AddOrUpdate(() => PrintTime(), Cron.Minutely);
...
private static void PrintTime() {
Console.WriteLine($"{DateTime.Now}");
}
如果我对Hangfire的理解是正确的,那么这只会序列化要调用的方法的名称,但不会序列化时间。
答案 1 :(得分:1)
对于我的问题中描述的问题,Stephen Vernyi发现了这个问题:由于Hangfire在JSON中序列化参数,因此第一个日期时间在序列化时被冻结,因此每个后续执行都会提供相同的输出。
但正如他所建议的那样,在编写方法时必须小心。
由于我随便尝试将这一切都工作,所有我的测试都在静态类中使用静态方法编写。而这样的实现提供了相同的冻结日期时间问题!
当我决定重构我的实现时,使用Job服务,在默认的ASP.Net Core IoC容器中注册,并设置为在每个请求时提供新的服务实例,它不仅解决了冻结输出问题,而且每个依赖注入遇到的问题。