Hangfire中的后台作业看起来像常规方法调用。它的大多数接口都使用表达式树来定义应该调用什么方法以及使用什么参数。后台作业可以同时使用实例和静态方法调用,如下例所示。
BackgroundJob.Enqueue<IEmailSender>(x => x.Send("hangfire@example.com"));
BackgroundJob.Enqueue(() => Console.WriteLine("Hello, world!"));
这些行使用表达式树,而不是像Action或Func这样的代理。与通常的方法调用不同,它们应该异步执行,甚至在当前流程之外执行。因此,上述方法调用的目的是收集并序列化以下信息。
- type 类型名称,包括命名空间和程序集。
- Method 方法名称及其参数类型。
- Argument 参数值。
序列化由Newtonsoft.Json包执行,生成的Json(如以下代码段所示)保存在存储中,以便其他进程使用。正如我们所看到的那样,所有的东西都是按值传递的,所以重数据结构也将被序列化,并消耗我们存储中的大量字节。
{"t":"System.Console, mscorlib","m":"WriteLine","p":["System.String"],"a":["Hello, world!"]}
t是类型名称,m是方法名称 p是参数类型 a是参数值
不保留其他信息。本地变量、实例和静态字段以及其他信息在我们的后台作业中不可用。
参数
也可以通过使用作业参数来保留将与后台作业关联的某些上下文。此功能可从后台作业过滤器中获得,并允许我们捕获和恢复一些环境信息。扩展筛选器使用作业参数来存储其他详细信息,而无需对方法调用元数据进行任何干预。
例如,CaptureCultureAttribute筛选器在创建后台作业时使用作业参数来捕获CurrentCulture和CurrentUICulture,并在即将处理该作业时将其还原。
无论如何,不保留其他上下文数据。作用域、全局变量、HttpContext实例和当前用户ID不会自动保留。
状态
每个后台作业在每个时刻都有一个与之相关的特定状态,该状态定义了如何以及何时处理它。有很多内置状态,如排队(Enqueued)、计划(Scheduled)、等待(Awaiting)、处理(Processing)、失败(Failed)、成功(Succeeded)和删除(Deleted),也可以实现自定义状态。
在后台处理过程中,后台作业从一个状态移动到另一个状态,并执行一些副作用。因此,Hangfire可以被视为后台作业的状态机。已处理的后台作业以最终状态结束(仅限“成功”和“已删除”内置状态,但不包括“失败”状态),默认情况下24小时后将自动过期。
通过调用WithJobExpirationTimeout方法,可以按以下方式全局配置过期时间。但是我们应该确保在UseXXXStorage之后调用这个方法,否则我们会得到一个编译错误。
GlobalConfiguration.Configuration
.UseXXXStorage(/* ... */)
.WithJobExpirationTimeout(TimeSpan.FromHours(6));