Hangfire可用作任務調度,類似延遲任務、隊列任務、批量任務和定時任務等。
一、nuget Hangfire包
找到Hangfire.AspNetCore和Hangfire.SqlServer包,可以在nuget面板中找到或直接像如下方式安裝:
Install Package Hangfire.AspNetCore
Install Package Hangfire.SqlServer
二、在Startup.cs文件中加入以下代碼:
寫一個Hangfire的擴展類,如下所示:
public static class HangFireModule
{
public static IApplicationBuilder UseHangfire(this IApplicationBuilder app)
{
app.UseHangfireServer();
app.UseHangfireDashboard();
return app;
}
public static IServiceCollection AddHangfire(this IServiceCollection services)
{
services.AddHangfire(x => x.UseSqlServerStorage(ConfigurationSetting.Configuration["ConnectionString:MyDb_Hangfire"]));
return services;
}
}
在Startup的ConfigureServices方法中,加入services.AddHangfire();
在Startup的Configure方法中,加入app.UseHangfire();
三、自動加入任務
1.在當前模塊中,新創建一個名為IHangfireTask的接口,將其注冊為瞬時生命周期服務。我們將要實現的是,從此以后,繼承該接口的類型都會被自動加入到任務調度中。
/// <summary>
/// Hangfire任務接口,任何繼承該接口的都會加入到Hangfire任務
/// </summary>
public interface IHangfireTask : ITransient {
/// <summary>
/// 運行hangfire任務
/// </summary>
void Run();
}
ITransient接口的作用就是,將所有繼承ITransient的接口和類型注冊為瞬時生命周期的服務。
2.在HangFireModule中新增一個UseHangfireTask擴展方法,目的是在Startup的Configure方法中使用,在程序啟動的時候就執行該方法。
//運行Hangfire任務
public static void UseHangfireTask(this IApplicationBuilder app) {
//找到繼承了IHangfireTask接口的實例
IList<IHangfireTask> list = ServiceLocator.Services.GetServices<IHangfireTask>()?.ToList();
if (list?.Count > 0) {
foreach (var item in list) {
item.Run();
}
}
}
加入到Startup的Configure方法中:
public void Configure(IApplicationBuilder app, IHostingEnvironment env,IServiceProvider serviceProvider)
{
ServiceLocator.SetServices(serviceProvider);
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler();
}
app.UseMvc();
app.UseSwagger();
app.UseSwaggerUi();
app.UseHangfire();
app.UseHangfireTask();
}
如此這樣,我們就做到了在程序剛啟動時,程序就會自動去找到繼承自IHangfireTask接口的所有類型並運行它們的Run()方法。
我們可以在Run()方法中實現諸如Hangfire的BackgroundJob或RecurringJob等任務。
接下來我們就用代碼來實現一下!
我們現在想實現一個定時任務,則看如下代碼:
public class RecurringTask:IHangfireTask
{
private log4net.ILog log => LogHelper.Log4NetInstance.LogFactory(typeof(RecurringTask));
public void RunTask()
{
log.Info("每分鍾執行一次定時任務");
}
public void Run()
{
RecurringJob.AddOrUpdate(()=> RunTask(), "* * * * *");
}
}
這里有一個地方需要注意,在使用RecurringJob或BackgroundJob的時候,就例如()=> RunTask()這個,RunTask方法的訪問修飾符必須是public。如果有必要,盡量在RunTask方法內被調用的其他方法的訪問修飾符也定義為public。
在Hangfire中,Cron表達式包含五個字段:分鍾、小時、日期、月份、周,因此定時任務最低也只能是一分鍾,沒有秒數可供選擇。
接下來我們看看程序運行的結果:

四、Hangfire的基本任務
1. BackgroundJob.Enqueue
作用:將一個任務放入到某個持久化的隊列中並挨個執行,以便程序可以繼續執行其他代碼。該任務只執行一次。
實現:BackgroundJob.Enqueue(() => RunTask());
2. BackgroundJob.Schedule
作用:將一個任務延遲到某個時間點后執行。
實現:BackgroundJob.Schedule(() => RunTask(), TimeSpan.FromSeconds(30));
即在30秒后才執行RunTask()方法。
3. RecurringJob.AddOrUpdate
作用:重復執行一個任務,一般用作定時任務處理。
實現:RecurringJob.AddOrUpdate(()=> RunTask(), "* * * * *");
即每分鍾都執行一次RunTask()方法。
4. BackgroundJob.ContinueWith
作用:類似工作流的形式,將多個任務連接起來按照順序執行。
實現:
string jobId = BackgroundJob.Schedule(() => Console.WriteLine("第一個任務"),TimeSpan.FromSeconds(10));
BackgroundJob.ContinueWith(jobId, () => RunTask());
注意:以上RunTask()方法的訪問修飾符必須是public。

