【注意】最后更新于 June 22, 2020,文中内容可能已过时,请谨慎使用。
Hangfire 是一个和 Quartz.Net 差不多的库,但是比较好的是 Hangfire 提供了web界面。
我的需求很简单,简单的一个控制台中能替代 Quartz.Net 执行任务。
开发环境
VS 2019 / .NET Framework 4.6.2
Demo构建
需要如下 Nuget 包
1
2
3
4
5
|
Install-Package Microsoft.AspNet.WebApi.OwinSelfHost
Install-Package Microsoft.Owin.Diagnostics
Install-Package Microsoft.Owin.Host.SystemWeb
Install-Package Hangfire
Install-Package Hangfire.Console
|
如果是非持久化存储,则安装
1
|
Install-Package Hangfire.MemoryStorage
|
持久化的话官方有提供数据库和Redis的选项,但是Redis是收费选项。
这里可以用开源版本来替代
1
|
Install-Package Hangfire.Redis.StackExchange
|
Program.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
private static void Main(string[] args)
{
// Redis 配置
var redisOption = new RedisStorageOptions()
{
Db = 10,
Prefix = "TestA:"
};
// 使用Redis存储
GlobalConfiguration.Configuration.UseRedisStorage("127.0.0.1", redisOption);
// 注册一个计划任务
RecurringJob.AddOrUpdate("输出时间", (() => JobCenter.JobA()), Cron.Minutely);
// 注册个OWIN 可以在本机开启控制台
StartOptions options = new StartOptions();
options.Urls.Add("http://localhost:9095");
WebApp.Start<Startup>(options);
// 阻止控制台关闭
Thread.Sleep(Timeout.Infinite);
}
|
Startup.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
using Hangfire;
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(ConsoleApp1.Startup))]
namespace ConsoleApp1
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
// 有关如何配置应用程序的详细信息,请访问 https://go.microsoft.com/fwlink/?LinkID=316888
app.UseHangfireDashboard();
app.UseHangfireServer();
}
}
}
|
调试
启动控制台,可见计划任务开始执行了。

打开网页 http://localhost:9095/hangfire

可以看见计划任务的执行记录,带入参数等。

执行模式
Hangfire 的执行模式免费的状态下有4种
Fire-and-forget 立即执行
1
|
BackgroundJob.Enqueue(() => Console.WriteLine("Hello, world!"));
|
单次执行咯…
Schedule 周期任务
1
|
BackgroundJob.Schedule((() => Console.Write(".")), TimeSpan.FromMinutes(1));
|
这个模式会根据时间间隔重复执行任务。
Crontab 计划任务
1
2
|
RecurringJob.AddOrUpdate("输出时间", (() => JobCenter.JobA()), Cron.Minutely);
RecurringJob.AddOrUpdate("输出时间", (() => JobCenter.JobA()), "0 */1 * ? * *");
|
在这种模式下,可以设置Job的名称。这个名称可以在控制台中看见,字段是”编号“。
目前用的最多的应该就这种模式了。
ContinueJobWith 连续性任务
1
2
|
var jobId = BackgroundJob.Enqueue(() => Thread.Sleep(1000));
BackgroundJob.ContinueJobWith(jobId, () => Console.WriteLine("完成"));
|
这种模式是通过获取上个任务的ID,当上个任务完成后执行任务。
任务的异常处理
任务异常处理可以通过在方法上增加修饰器来进行。
1
2
3
4
5
6
7
8
|
public class JobCenter
{
[AutomaticRetry(Attempts = 5)]
public static void JobA()
{
Debug.WriteLine(DateTime.Now);
}
}
|
其中的
1
|
[AutomaticRetry(Attempts = 5)]
|
就是当异常出现时,自动重试,当达到5次失败后抛出异常。
AutomaticRetry的重试次数预设为10次,如果不想重试可以直接设置为0。
如果想要全局设置这个重试次数,可以使用
1
|
GlobalJobFilters.Filters.Add(new AutomaticRetryAttribute { Attempts = 5 });
|
AutomaticRetry中还有很多参数,例如这种
1
|
[AutomaticRetry(Attempts = 5 ,DelaysInSeconds = new[] { 3, 10, 15 }, OnAttemptsExceeded = AttemptsExceededAction.Delete)]
|
DelaysInSeconds 指定了重试的时间间隔
OnAttemptsExceeded 当失败后的操作,是归类到删除还是失败
同时在控制台中,也可很清晰的看见异常的信息

Queue设定

Queue的命名规则:小写字母,数字,下划线和破折号
当配置Queue名称后,UseHangfireServer 中也需要传入名称才能使用。

其他
并发限制
1
|
[DisableConcurrentExecution(秒数)]
|
任务名称
