C# HangFire的使用及说明

 更新时间:2026年05月25日 17:15:03   作者:陈同学呀  
Hangfire是一个.NET后台任务处理库,支持fire-and-forget、延迟和re、周期性任务等功能,内置持久化存储和可视化监控,适用于构建高效、可靠的后台作业系统

一、含义

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

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

二、核心作用

1.任务调度与执行

  • 即时任务(Fire-and-forget):异步执行,如日志记录、邮件发送
BackgroundJob.Enqueue(() => Console.WriteLine("Task executed!"));  
  • 延迟任务(Delayed):指定未来时间执行,如订单超时取消。
BackgroundJob.Schedule(() => SendReminder(), TimeSpan.FromHours(24));  
  • 周期性任务(Recurring):基于 Cron 表达式定时执行,如每日数据备份。
RecurringJob.AddOrUpdate("daily-job", () => SyncData(), Cron.Daily);  
  • 连续性任务(Continuations):任务链式执行,如支付成功后通知发货

2.持久化与可靠性

  • 任务信息存储于数据库(SQL Server/Redis 等),应用崩溃或重启后自动恢复。

  • 内置重试机制:任务失败时自动重试(可配置次数)

3.分布式支持

  • 支持多节点部署,实现高可用和负载均衡。

  • 可通过 Redis 提升性能,适应高并发场景

4.可视化监控

  • 内置 Dashboard 实时展示任务状态、日志和执行历史,支持手动触发或取消任务

5.扩展性与集成

  • 支持依赖注入(如 Autofac、Ninject)。

  • 可配置多队列优先级和并发控制

任务类型适用场景代码示例
即时任务异步日志、邮件通知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.不支持秒级定时任务

  • 最小调度单位为分钟(依赖 NCrontab 组件),秒级任务需改用 Quartz.NET

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

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

  • 应用重启导致任务丢失

  • 缺乏线程安全性和持久化保障

3.性能瓶颈

  • SQL Server 存储依赖轮询机制,高并发场景下可能延迟(可通过 Redis 或 MSMQ 缓解)

4.中文支持问题

  • 部分版本(如 1.8.14)Dashboard 中文显示异常,需降级或手动修复

五、Hangfire与Quartz.Net对比

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

总结

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

相关文章

  • c# 如何对网络信息进行相关设置(ip,dns,网关等)

    c# 如何对网络信息进行相关设置(ip,dns,网关等)

    这篇文章主要介绍了c# 网络适配器的相关操作,帮助大家更好的理解和学习使用c#,感兴趣的朋友可以了解下
    2021-03-03
  • C#使用ScrapySharp快速从网页采集数据

    C#使用ScrapySharp快速从网页采集数据

    这篇文章介绍了使用ScrapySharp快速从网页采集数据的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-06-06
  • C#委托与冒泡排序实例

    C#委托与冒泡排序实例

    这篇文章介绍了C#委托与冒泡排序的实例,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-04-04
  • C#端口扫描器的编写方法

    C#端口扫描器的编写方法

    这篇文章主要为大家详细介绍了C#端口扫描器的编写方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-07-07
  • 在C# .NET Core中绘制Chart图表并导出到PDF的实现方法

    在C# .NET Core中绘制Chart图表并导出到PDF的实现方法

    正好最近的项目需要在后端绘制Chart图标并进行导出,查阅相关资料后想着记录以下,本文将详细介绍在.NET Core环境中如何绘制Chart图表并将其导出到PDF文档中,并分析这种实现方式的技术价值和应用场景,需要的朋友可以参考下
    2025-10-10
  • C#实现求一组数据众数的方法

    C#实现求一组数据众数的方法

    这篇文章主要介绍了C#实现求一组数据众数的方法,这里以浮点型数组为例分析了C#求众数的算法原理与实现技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-08-08
  • C#中的DataTable查询实战教程

    C#中的DataTable查询实战教程

    这篇文章主要介绍了C#中的DataTable查询实战教程,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01
  • 利用C#实现获取与监控电脑系统信息

    利用C#实现获取与监控电脑系统信息

    在C#中,获取与监控电脑系统信息通常可以通过多种方式实现,这篇文章主要为大家整理了几种常见的方法及其示例代码,希望对大家有所帮助
    2024-11-11
  • 使用策略模式实现报警服务示例详解(短信报警)

    使用策略模式实现报警服务示例详解(短信报警)

    服务的功能:这个服务就是能够实现多通路报警的服务,比如邮件报警、客户端报警、短信报警等,该服务灵活性还不错,比较方便扩展
    2014-01-01
  • C#自定义处理xml数据类实例

    C#自定义处理xml数据类实例

    这篇文章主要介绍了C#自定义处理xml数据类,涉及C#针对XML的打开、读写等常用操作,并将其封装进一个类中以便于调用,非常具有实用价值,需要的朋友可以参考下
    2015-03-03

最新评论