一、创建 .NET 8 项目
首先创建一个 .NET 8 项目(ASP.NET Core Web 应用或控制台应用),这里以 ASP.NET Core Web API 为例。
二、安装必要的 NuGet 包
核心包(适用于 ASP.NET Core)
Install-Package Hangfire.AspNetCore
存储后端(选择一个)
Install-Package Hangfire.SqlServer      # SQL Server
Install-Package Hangfire.Redis.StackExchange  # Redis
Install-Package Hangfire.PostgreSql    # PostgreSQL
其他拓展
Install-Package Microsoft.Data.SqlClient
Install-Package Swashbuckle.AspNetCore三、完整配置步骤(.NET 8 + SQL Server)
- 
配置连接字符串 
 在 appsettings.json 中添加数据库连接:
 需先创建一个数据库Windows本机连接 
 {
 "ConnectionStrings": {
 "HangfireConnection": "Server=localhost;Database=HangfireNet8;Integrated Security=True;TrustServerCertificate=True"
 }
 }IP账号密码连接 
 "ConnectionStrings": {
 "HangfireConnection": "Server=127.0.0.1;Database=HangfireDB;User Id=sa;Password=123456;TrustServerCertificate=True;Encrypt=False"
 }
- 
配置 Program.cs 
            
            
              csharp
              
              
            
          
          using Hangfire;
using Hangfire.Dashboard;
using Hangfire.SqlServer;
using Microsoft.Extensions.Logging;
using System.Net;
var builder = WebApplication.CreateBuilder(args);
// 添加 Hangfire 服务
builder.Services.AddHangfire(configuration => configuration
    .SetDataCompatibilityLevel(CompatibilityLevel.Version_180)
    .UseSimpleAssemblyNameTypeSerializer()
    .UseRecommendedSerializerSettings()
    // 配置 SQL Server 存储
    .UseSqlServerStorage(builder.Configuration.GetConnectionString("HangfireConnection"), new SqlServerStorageOptions
    {
        CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
        SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
        QueuePollInterval = TimeSpan.Zero,
        UseRecommendedIsolationLevel = true,
        DisableGlobalLocks = true,
        EnableHeavyMigrations = true
    })
);
// 添加 Hangfire 服务器
builder.Services.AddHangfireServer(options =>
{
    options.WorkerCount = Math.Max(Environment.ProcessorCount * 5, 10);
    options.Queues = new[] { "high", "medium", "low" };
    options.ShutdownTimeout = TimeSpan.FromMinutes(1);
});
// 添加控制器和Swagger服务
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// 注册应用服务
builder.Services.AddScoped<ITaskService, TaskService>();
var app = builder.Build();
var isDevelopment = app.Environment.IsDevelopment();
// 配置HTTP请求管道
if (isDevelopment)
{
    app.UseSwagger();
    app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
// 启用 Hangfire 仪表板
app.UseHangfireDashboard("/hangfire", new DashboardOptions
{
    Authorization = new[] { new HangfireAuthFilter(isDevelopment) }
});
// 定义任务
using (var scope = app.Services.CreateScope())
{
    var services = scope.ServiceProvider;
    try
    {
        var taskService = services.GetRequiredService<ITaskService>();
        // 1. 即时任务
        BackgroundJob.Enqueue(() => taskService.ProcessData("initial"));
        // 2. 延迟任务(30分钟后执行)
        BackgroundJob.Schedule(
            () => taskService.SendNotification("delayed"),
            TimeSpan.FromMinutes(1)
        );
        // 3. 循环任务(每小时执行一次)
        RecurringJob.AddOrUpdate(
            "hourly-cleanup",
            () => taskService.CleanupResources(),
            Cron.Hourly,
            TimeZoneInfo.Local
        );
        // 4. 延续任务
        var parentJobId = BackgroundJob.Enqueue(() => taskService.ProcessOrder(1001));
        BackgroundJob.ContinueWith(
            parentJobId,
            () => taskService.CompleteOrder(1001)
        );
    }
    catch (Exception ex)
    {
        var logger = services.GetRequiredService<ILogger<Program>>();
        logger.LogError(ex, "注册Hangfire任务时发生错误");
    }
}
app.MapControllers();
app.Run();
// 自定义授权过滤器 - 修复空值问题
public class HangfireAuthFilter : IDashboardAuthorizationFilter
{
    private readonly bool _isDevelopment;
    public HangfireAuthFilter(bool isDevelopment)
    {
        _isDevelopment = isDevelopment;
    }
    public bool Authorize(DashboardContext context)
    {
        // 确保上下文不为空
        if (context == null)
            return false;
        // 获取HTTP上下文并检查
        var httpContext = context.GetHttpContext();
        if (httpContext == null)
            return false;
        // 开发环境直接允许访问
        if (_isDevelopment)
            return true;
        // 生产环境检查是否为本地访问
        var localIpAddress = httpContext.Connection.LocalIpAddress;
        if (localIpAddress == null)
            return false;
        // 明确检查是否为回环地址(IPv4和IPv6)
        return IPAddress.IsLoopback(localIpAddress);
    }
}
// 任务服务接口
public interface ITaskService
{
    void ProcessData(string data);
    void SendNotification(string message);
    void CleanupResources();
    void ProcessOrder(int orderId);
    void CompleteOrder(int orderId);
}
// 任务服务实现
public class TaskService : ITaskService
{
    private readonly ILogger<TaskService> _logger;
    // 确保日志服务不为空
    public TaskService(ILogger<TaskService> logger)
    {
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }
    public void ProcessData(string data)
    {
        if (string.IsNullOrEmpty(data))
            throw new ArgumentException("数据不能为空", nameof(data));
        _logger.LogInformation("处理数据: {Data}", data);
    }
    public void SendNotification(string message)
    {
        if (string.IsNullOrEmpty(message))
            throw new ArgumentException("消息不能为空", nameof(message));
        _logger.LogInformation("发送通知: {Message}", message);
    }
    public void CleanupResources()
    {
        _logger.LogInformation("清理资源于 {Time}", DateTime.Now);
    }
    public void ProcessOrder(int orderId)
    {
        if (orderId <= 0)
            throw new ArgumentOutOfRangeException(nameof(orderId), "订单ID必须大于0");
        _logger.LogInformation("处理订单: {OrderId}", orderId);
    }
    public void CompleteOrder(int orderId)
    {
        if (orderId <= 0)
            throw new ArgumentOutOfRangeException(nameof(orderId), "订单ID必须大于0");
        _logger.LogInformation("订单完成: {OrderId}", orderId);
    }
}四、数据库初始化
首次运行应用时,Hangfire 会自动在指定的数据库中创建所需的表结构(约 15 张表),无需手动创建。
五、访问 Hangfire 仪表板
启动应用后,访问 https://localhost:端口/hangfire 即可打开管理界面,在这里可以:
查看所有任务的执行状态
手动触发、暂停或删除循环任务
重试失败的任务
监控服务器状态和性能
