ASP.NET 使用 Hangfire 背景程式、排程執行工作


  1. 說明
  2. 使用方式
  3. 參考資料

除了使用 Windows Service 或者是 Task Scheduler 搭配 Console 來排程執行程式,使用 HangFire 自帶程式執行的 Dashboard,使用相關的 API 也更容易進行排程的新增、修改與刪除等管理,不需要額外開發 Windows Service 或者 Console。

logo

說明

使用 Hangfire 的背景程式自由度與 Console 相仿,在 Class 當中能夠自由地發揮。此外與 Task Scheduler 以及 Windows Service 相比,自帶的 Dashbaord 不但對於除錯更方錯,預設也會自動重新嘗試失敗的工作,也能夠手動快速地重新執行失敗的工作。

使用方式

首先需要使用 Nuget 進行安裝 hangfire,只要安裝 hangfire 相關的 packages 就會自己安裝,預設上排程的資料庫是使用 SQL Server,如果需要使用其他的 Provider 可以在安裝相關的 packages,例如 SQLite。

以下是安裝 hangfire package 後自動安裝的相關 package。

<package id="Hangfire" version="1.7.30" targetFramework="net48" />
<package id="Hangfire.Core" version="1.7.30" targetFramework="net48" />
<package id="Hangfire.SqlServer" version="1.7.30" targetFramework="net48" />
<package id="Owin" version="1.0" targetFramework="net48" />

只要安裝好 Hangfire,並且加入 Startup.cs 並設定資料庫的連線方式後,就可以藉由 /hangfire 的方式連線到 Dashboard。

而預設上 Dashbaord 只能在本機登入,此外也可以在 Startup 搭配組態的設定來達到身分驗證的效果。

Controller/Startup.cs

using Hangfire;
using Microsoft.Owin;
using Owin;

[assembly: OwinStartup(typeof(MyWebApplication.Startup))]
namespace MyWebApplication
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            GlobalConfiguration.Configuration
                .UseSqlServerStorage("Server=.; Database=Hangfire; Integrated Security=SSPI;");

            app.UseHangfireDashboard();
            app.UseHangfireServer();
        }
    }
}

Hangfire Dashboard

也可以從資料庫觀察到,資料表已經被自動建立完成了,之後只要有新增、刪除排程 Job 或者有執行失敗等紀錄,都會保存於資料庫當中。

Hangfire Database & Tables

接著使用 RecurringJob.AddOrUpdate 負責加入排程作業,範例是每分鐘進行一次 Jobs 類別的 CreateFile。

Controller/HomeController.cs

public ActionResult AddJob()
{
    RecurringJob.AddOrUpdate(
        () => new Jobs().CreateFile()
        , Cron.Minutely);

    return View();
}

排程的作業內容,自動在特定路徑建立檔案並寫入當下的日期時間作為內容。

Model/Jobs.cs

using System;
using System.IO;

namespace HangfireProject.Models
{
    public class Jobs
    {
        public void CreateFile()
        {
            var guid = Guid.NewGuid().ToString().Substring(0, 8);

            File.WriteAllText(
              $"C:/Temp/{guid}.txt", 
              DateTime.Now.ToString());
        }
    }
}

Job 在實際執行的時候,無法取用 ASP.NET MVC 環境中的物件,而是會由獨立的 Thread 進行 Job 類型中的物件,因此在設計上要避免使用如 HttpContext 等 ASP.NET Runtime 等變數。

參考資料

使用HANGFIRE處理ASP.NET MVC/WEB API長時間與排程工作 | KingKong Bruce記事

Hangfire 初學 | Art的辦公桌

hangfire | 黑暗執行緒