以下是在 WPF 项目中集成 Hangfire 的完整指南,涵盖核心功能(定时任务、后台任务、重试机制)和代码示例:
一、Hangfire 简介
- 定位:开源的 .NET 任务调度框架,专注于 定时任务、后台任务 和 重试机制。
- 适用场景:
- 定时发送邮件、报表生成等重复性任务。
- 长时间运行的异步任务(如文件导出、数据同步)。
- 需要任务失败自动重试的场景。
- 特点:
- 支持 SQL Server、Redis、MongoDB 等多种存储。
- 提供直观的 Web 界面监控任务状态(需配合 Hangfire Dashboard)。
- 轻量级(核心库仅依赖
System.Threading
)。
二、在 WPF 项目中使用 Hangfire
1. 安装依赖
通过 NuGet 安装 Hangfire.Core 和存储提供程序(以 SQL Server 为例):
Install-Package Hangfire.Core -Version 1.9.0
Install-Package Hangfire.SqlServer -Version 1.9.0
2. 配置 Hangfire
在 WPF 项目的入口类(如 App.xaml.cs
)中初始化 Hangfire:
using Hangfire;
using Hangfire.SqlServer;
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
// 配置 SQL Server 数据库连接
var connectionString = "YourSqlConnection";
GlobalConfiguration.Configuration
.UseSqlServerStorage(connectionString)
.UseConsoleLogger(); // 输出日志到控制台
// 启动 Hangfire 服务(非 Web 环境需手动启动)
using (var server = new BackgroundJobServer())
{
server.Start();
}
}
}
三、定义任务
方式一:使用方法委托
// 定义简单任务
RecurringJob.AddOrUpdate(
"SendDailyReport",
() => SendDailyReport(),
"0 0 6 * * *"); // 每天 6:00 执行
// 定义带参数的任务
RecurringJob.AddOrUpdate(
"ProcessOrder",
(orderId) => ProcessOrder(orderId),
"0 */5 * * *",
new { orderId = 123 });
方式二:实现 IJob
接口
public class SendEmailJob : IJob
{
public void Execute(IJobExecutionContext context)
{
// 发送邮件逻辑
Console.WriteLine("Email sent to: " + context.JobData["Recipient"]);
}
}
// 调度任务
BackgroundJob.Enqueue(new SendEmailJob { Recipient = "user@example.com" });
四、任务调度与执行
4.1 启动调度器
在 WPF 启动时启动后台任务服务:
var server = new BackgroundJobServer();
server.Start();
4.2 手动触发任务
// 立即执行一次任务
BackgroundJob.Enqueue(() => DoSomething());
// 延迟执行任务(5秒后)
BackgroundJob.Schedule(() => DoSomething(), TimeSpan.FromSeconds(5));
4.3 重试机制
通过 EnqueueWithRetry
实现自动重试:
BackgroundJob.EnqueueWithRetry(
() => RiskyOperation(),
retry: 3, // 最大重试次数
delay: TimeSpan.FromSeconds(30), // 重试间隔
onException: ex => ex is IOException); // 仅在 IOException 时重试
五、WPF UI 集成
5.1 显示任务状态
通过 Hangfire Dashboard(需安装 Hangfire.AspNetCore
并配置 Web 端):
Install-Package Hangfire.AspNetCore
在 ASP.NET Core 项目中启用 Dashboard:
public void ConfigureServices(IServiceCollection services)
{
services.AddHangfireServer();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseHangfireDashboard("/hangfire");
}
5.2 在 WPF 中调用 Hangfire API
通过 HTTP 请求与 Hangfire 交互(需启用 CORS):
private async void btnSchedule_Click(object sender, RoutedEventArgs e)
{
using (var client = new HttpClient())
{
var content = new StringContent(
JsonConvert.SerializeObject(new { JobName = "SendReport", Schedule = "0 0 6 * * *" }),
Encoding.UTF8,
"application/json");
var response = await client.PostAsync("http://localhost:5000/hangfire/api/jobs/schedule", content);
if (response.IsSuccessStatusCode)
{
MessageBox.Show("Task scheduled successfully!");
}
}
}
六、持久化配置
6.1 使用 SQL Server 存储
在 app.xaml.cs
中配置连接字符串:
var connectionString = "Data Source=.\sqlserver;Initial Catalog=HangfireDb;Integrated Security=True";
GlobalConfiguration.Configuration
.UseSqlServerStorage(connectionString)
.WithTablePrefix("Hangfire"); // 自定义表前缀(可选)
6.2 初始化数据库
运行以下命令创建 Hangfire 表:
dotnet ef database update
七、示例:完整 WPF 项目
项目结构
Tasks.cs
: 定义任务逻辑MainWindow.xaml.cs
: WPF 界面集成App.xaml.cs
: Hangfire 初始化
关键代码片段
Tasks.cs:
public class EmailService
{
public void SendDailyReport()
{
Console.WriteLine("Generating daily report...");
// 实际发送邮件逻辑
}
}
public class OrderProcessor
{
public void ProcessOrder(int orderId)
{
Console.WriteLine($"Processing order {orderId}...");
// 模拟失败操作
if (orderId % 2 == 0)
throw new InvalidOperationException("Order processing failed.");
}
}
MainWindow.xaml.cs:
public partial class MainWindow : Window
{
private readonly IBackgroundJobClient _jobClient;
public MainWindow()
{
InitializeComponent();
// 初始化 Hangfire 客户端
_jobClient = new BackgroundJobClient();
// 绑定按钮事件
btnSchedule.Click += BtnSchedule_Click;
btnRetry.Click += BtnRetry_Click;
}
private void BtnSchedule_Click(object sender, RoutedEventArgs e)
{
// 调度每日报告任务
_jobClient.Enqueue(() => EmailService.SendDailyReport());
MessageBox.Show("Daily report task scheduled!");
}
private void BtnRetry_Click(object sender, RoutedEventArgs e)
{
// 手动触发失败任务的重新尝试
var failedJobs = _jobClient.GetFailedJobs(0, 100);
foreach (var job in failedJobs)
{
_jobClient.RetryJob(job.Id);
}
}
}
八、核心优势对比
特性 | Hangfire | 其他框架(如 Elsa Workflow) |
---|---|---|
专注领域 | 任务调度、后台任务、重试机制 | 流程编排、状态管理 |
执行模式 | 轻量级后台线程 + 分布式调度 | 单次或长时间运行工作流实例 |
持久化 | 支持 SQL、Redis 等多种存储 | 依赖 WF 持久化提供程序 |
社区生态 | 成熟,文档齐全 | 较小众(如 Elsa 社区支持较好) |
适用场景
- 需要定时任务:如每日报表、定时通知。
- 异步任务处理:如文件上传、长耗时计算。
- 故障恢复:自动重试失败任务,无需人工干预。