Hangfire为我们的后台作业提供了取消令牌的支持,以让他们知道何时启动了关闭请求,或作业性能被中止。在前一种情况下,作业将自动放回队列的开头,允许Hangfire在重新启动后处理它。
我们应该尽可能多地使用取消令牌——它们大大降低了应用程序关闭时间和出现ThreadBortException的风险。
取消令牌
从Hangfire 1.7.0开始,可以为此使用常规的CancellationToken类。与以前基于IJobCancellationToken的实现不同,新的实现是完全异步的,不会导致立即的存储请求,因此现在即使在紧密的循环中也可以安全地使用它。
public async Task LongRunningMethod(CancellationToken token)
{
for (var i = 0; i < Int32.MaxValue; i++)
{
await Task.Delay(TimeSpan.FromSeconds(1), token);
}
}
当创建这样的后台作业时,可以使用任何CancellationToken实例,它将在执行后台作业之前被内部替换。
BackgroundJob.Enqueue<IService>(x => x.LongRunningMethod(CancellationToken.None));
专用后台进程正在监视方法中具有取消令牌参数的所有当前后台作业,并轮询存储以监视其当前状态。当检测到状态变化或请求关闭时,相应的取消令牌被取消。
轮询延迟可通过BackgroundJobServerOptions.CancellationCheckInterval服务器选项进行配置。
services.AddHangfireServer(new BackgroundJobServerOptions
{
CancellationCheckInterval = TimeSpan.FromSeconds(5) // Default value
});
IJobCancellationToken
这是取消令牌的过时实现。尽管它以与基于CancellationToken的异步实现方式相同的方式实现,但我们不能在许多用例中使用它。向后兼容是现在使用此接口的唯一原因,因此我们应该更喜欢在新逻辑中使用CancellationToken参数。
接口包含ThrowIfCancellationRequested方法,该方法在请求取消时引发OperationCanceledException:
public void LongRunningMethod(IJobCancellationToken cancellationToken)
{
for (var i = 0; i < Int32.MaxValue; i++)
{
cancellationToken.ThrowIfCancellationRequested();
Thread.Sleep(TimeSpan.FromSeconds(1));
}
}
当我们想将这样的方法调用作为后台作业排入队列时,我们可以将null值作为token参数的参数传递,或者使用JobCancellationToken.null属性告诉代码读取器我们做得很正确:
BackgroundJob.Enqueue(() => LongRunningMethod(JobCancellationToken.Null));
实现自动解决。Hangfire负责在运行时的作业执行期间传递IJobCancellationToken的正确非空实例。