C#教程

关注公众号 jb51net

关闭
首页 > 软件编程 > C#教程 > C# HangFire的使用

C# HangFire的使用及说明

作者:陈同学呀

Hangfire是一个.NET后台任务处理库,支持fire-and-forget、延迟和re、周期性任务等功能,内置持久化存储和可视化监控,适用于构建高效、可靠的后台作业系统

一、含义

Hangfire 是一个 .NET 后台任务处理库,允许开发者在 ASP.NET、控制台应用或 Windows 服务中创建和管理后台作业(如定时任务、队列任务)。

它通过持久化存储(如 SQL Server、Redis)保存任务状态,确保应用重启后任务不丢失,并内置 Web 仪表盘(Dashboard)实现任务可视化监控

二、核心作用

1.任务调度与执行

BackgroundJob.Enqueue(() => Console.WriteLine("Task executed!"));  
BackgroundJob.Schedule(() => SendReminder(), TimeSpan.FromHours(24));  
RecurringJob.AddOrUpdate("daily-job", () => SyncData(), Cron.Daily);  

2.持久化与可靠性

3.分布式支持

4.可视化监控

5.扩展性与集成

任务类型适用场景代码示例
即时任务异步日志、邮件通知BackgroundJob.Enqueue(() => Log("Info"))
延迟任务订单超时处理、定时提醒BackgroundJob.Schedule(() => CancelOrder(), TimeSpan.FromMinutes(30))
周期性任务每日数据备份、报表生成RecurringJob.AddOrUpdate("backup", () => BackupData(), Cron.Daily)
连续性任务支付→发货→通知工作流BackgroundJob.ContinueJobWith(parentId, () => ShipProduct())

三、用法(以 ASP.NET Core 为例)

安装与配置

Install-Package Hangfire.AspNetCore
Install-Package Hangfire.Redis.StackExchange  # 若用 Redis 存储

服务注册(Startup.cs)

public void ConfigureServices(IServiceCollection services) {
    services.AddHangfire(config => config
        .UseRedisStorage(redisConnectionString)  // 或 UseSqlServerStorage()
    );
    services.AddHangfireServer();  // 启动后台服务
}

启用 DashboardStartup.cs

public void Configure(IApplicationBuilder app) {
    app.UseHangfireDashboard("/jobs");  // 访问路径:http://domain/jobs
    // 可选:添加身份验证过滤器
    app.UseHangfireServer();
}

创建任务示例

周期性库存同步

RecurringJob.AddOrUpdate("stock-sync", () => StockService.Sync(), "0 3 * * *"); // 每天3点执行

业务例子

我需要每天定时定点往大宽表中插入一次在线库存、当天入库、出库记录

using Hangfire;
using Hangfire.Annotations;
using Hangfire.Dashboard;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using WmsService.WmsStk.StkBalances;

namespace WmsService
{
    /// <summary>
    /// 后台工作任务配置
    /// </summary>
    public static class BackgroundConfigurer
    {
        /// <summary>
        /// 配置服务
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void Configure(IServiceCollection services, IConfiguration configuration)
        {
            // Hangfire 任务
            services.AddHangfire(config =>
            {
                config.UseSqlServerStorage(configuration.GetConnectionString("Wms"));
            });
        }

        /// <summary>
        /// 请求管道
        /// </summary>
        /// <param name="app"></param>
        /// <param name="configuration"></param>
        public static void UseBackground(IApplicationBuilder app, IConfiguration configuration)
        {
            app.UseHangfireDashboard("/hangfire", new DashboardOptions
            {
                Authorization = new[]
                {
                    new CustomAuthorizeFilter()
                }
            });

            app.UseHangfireServer();
            //// 每天凌晨12点
            //Cron.Daily(0, 0)

            // 每天中午12点
            //Cron.Daily(12, 0)

            // 每小时执行一次
            //Cron.Hourly()

            // 每30分钟执行一次
            //Cron.MinuteInterval(30)

            //定时调用方法AutoInsertInventoryRecord() 插入库存
            RecurringJob.AddOrUpdate<StkBalanceAppService>(x => x.AutoInsertInventoryRecord(), Cron.Daily(0, 1), TimeZoneInfo.Local);
        }
    }

    public class CustomAuthorizeFilter : IDashboardAuthorizationFilter
    {
        public bool Authorize([NotNull] DashboardContext context)
        {
            return true;
        }
    }
}
 /// <summary>
 /// 定时插入库存记录
 /// </summary>
 /// <returns></returns>
 public virtual async Task AutoInsertInventoryRecord()
 {
     //定时插入一条
     var now = DateTime.Now.Date;
     //now = DateTime.ParseExact("2025-02-20", "yyyy-MM-dd", CultureInfo.InvariantCulture);
     var startTime = now.AddDays(-1);
     //入库总数
     var inLists = await _inOrderDapperRepository.QueryInventoryReportByDay(startTime, now);
     //出库总数
     var outLists = await _outInvoiceDapperRepository.QueryOutboundReportByDay(startTime, now);
     //在线库存
     var onlineLists = await _outInvoiceDapperRepository.QueryOnlineBalanceReport();
     var lists = new List<WmsInventoryRecord>();
     foreach (var inDto in inLists)
     {
         WmsInventoryRecord inventoryRecord = new WmsInventoryRecord();
         inventoryRecord.MaterialCode = inDto.MaterialCode;
         inventoryRecord.InWareHouseQty = inDto.InQty;
         lists.Add(inventoryRecord);
     }
     foreach (var outDto in outLists)
     {
         WmsInventoryRecord inventoryRecord = new WmsInventoryRecord();
         inventoryRecord.MaterialCode = outDto.MaterialCode;
         inventoryRecord.OutBoundQty = outDto.OutQty;
         lists.Add(inventoryRecord);
     }
     foreach (var onlineDto in onlineLists)
     {
         WmsInventoryRecord inventoryRecord = new WmsInventoryRecord();
         inventoryRecord.MaterialCode = onlineDto.MaterialCode;
         inventoryRecord.OnlineInventory = onlineDto.OnlineQty;
         lists.Add(inventoryRecord);
     }
     await _wmsInventoryRecordDapperRepository.InsertManyAsync(lists);
 }

服务注册

   //后台工作任务配置
   BackgroundConfigurer.Configure(context.Services, configuration);


   BackgroundConfigurer.UseBackground(app, configuration);

四、缺陷与限制

1.不支持秒级定时任务

2.内存存储(MemoryStorage)的局限性

仅适用于开发和测试环境:

3.性能瓶颈

4.中文支持问题

五、Hangfire与Quartz.Net对比

对比项HangfireQuartz.NET
最小调度粒度分钟级秒级
可视化面板内置 Dashboard需第三方扩展
分布式支持基础多节点原生集群支持
适用场景常规后台任务、需可视化监控复杂调度、金融级精准定时

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文