编辑
2025-02-05
C# 应用
00
请注意,本文编写于 90 天前,最后修改于 90 天前,其中某些信息可能已经过时。

目录

简介
Hangfire的主要特性
安装和配置
安装Hangfire
基本配置
基本用法
创建和执行即发即弃作业
延迟作业
重复作业
批量处理与进度报告
定时报告生成与邮件发送
使用Hangfire进行缓存预热
最佳实践
结论

简介

Hangfire是一个强大的开源库,用于在.NET应用程序中执行后台作业。它提供了一种简单而有效的方式来处理各种类型的后台任务,如定时作业、延迟作业和重复作业等。本文将深入探讨Hangfire的特性,并通过多个实例演示其在C#项目中的应用。

Hangfire的主要特性

  • 持久性和可靠性:作业存储在持久化存储中(如数据库)
  • 分布式处理:支持多服务器环境
  • 自动重试:失败作业会自动重试
  • 实时监控:提供Web界面监控作业状态
  • 多种存储选项:支持SQL Server, Redis等
  • 易于集成:可以轻松集成到现有.NET项目中

安装和配置

安装Hangfire

使用NuGet包管理器安装Hangfire:

C#
Install-Package Hangfire

对于SQL Server存储,还需要安装:

PowerShell
Install-Package Hangfire.SqlServer

基本配置

Program.cs文件中配置Hangfire:

C#
// 添加Hangfire服务 builder.Services.AddHangfire(configuration => configuration .SetDataCompatibilityLevel(CompatibilityLevel.Version_170) .UseSimpleAssemblyNameTypeSerializer() .UseRecommendedSerializerSettings() .UseSqlServerStorage(_configuration.GetConnectionString("HangfireConnection"), new SqlServerStorageOptions { CommandBatchMaxTimeout = TimeSpan.FromMinutes(5), SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5), QueuePollInterval = TimeSpan.Zero, UseRecommendedIsolationLevel = true, DisableGlobalLocks = true })); // 添加Hangfire服务器 builder.Services.AddHangfireServer();

基本用法

创建和执行即发即弃作业

C#
public class EmailService { public void SendWelcomeEmail(string email) { // 发送欢迎邮件的逻辑 Console.WriteLine($"Welcome email sent to {email}"); } }
C#
[Route("api/[controller]")] [ApiController] public class UserController : ControllerBase { [HttpPost] public IActionResult Register(string email) { // 用户注册逻辑... // 创建后台作业发送欢迎邮件 BackgroundJob.Enqueue<EmailService>(x => x.SendWelcomeEmail(email)); return Ok("User registered successfully"); } }

延迟作业

C#
public class ReminderService { public void SendReminder(int userId, string message) { // 发送提醒的逻辑 Console.WriteLine($"Reminder sent to user {userId}: {message}"); } }
C#
[Route("api/[controller]")] [ApiController] public class TaskController : ControllerBase { [HttpPost] public IActionResult CreateTask(int userId, string taskDescription) { // 创建任务逻辑... // 创建延迟作业,24小时后发送提醒 BackgroundJob.Schedule<ReminderService>( x => x.SendReminder(userId, $"Don't forget your task: {taskDescription}"), TimeSpan.FromHours(24)); return Ok("Task created and reminder scheduled"); } }

image.png

重复作业

C#
public class DatabaseCleanupService { public void PerformCleanup() { // 数据库清理逻辑 Console.WriteLine("Database cleanup performed at: " + DateTime.Now); } }

Program.cs

C#
// 在这里设置重复作业 using (var scope = app.Services.CreateScope()) { var recurringJobManager = scope.ServiceProvider.GetRequiredService<IRecurringJobManager>(); recurringJobManager.AddOrUpdate<DatabaseCleanupService>( "database-cleanup", x => x.PerformCleanup(), Cron.Daily); }

批量处理与进度报告

这个例子展示了如何使用Hangfire处理大量数据,并报告进度。

C#
public class BatchProcessingService { private readonly ILogger<BatchProcessingService> _logger; public BatchProcessingService(ILogger<BatchProcessingService> logger) { _logger = logger; } public void ProcessLargeDataSet(int batchSize, int totalItems) { var batchCount = (int)Math.Ceiling((double)totalItems / batchSize); for (int i = 0; i < batchCount; i++) { var batchNumber = i; BackgroundJob.Enqueue(() => ProcessBatch(batchNumber, batchSize, totalItems)); } } public void ProcessBatch(int batchNumber, int batchSize, int totalItems) { var startIndex = batchNumber * batchSize; var endIndex = Math.Min(startIndex + batchSize, totalItems); for (int i = startIndex; i < endIndex; i++) { // 处理单个项目的逻辑 _logger.LogInformation($"Processing item {i}"); } var progress = (int)((endIndex / (double)totalItems) * 100); _logger.LogInformation($"Batch {batchNumber} completed. Overall progress: {progress}%"); } }
C#
[Route("api/[controller]")] [ApiController] public class DataProcessingController : ControllerBase { private readonly BatchProcessingService _batchProcessingService; public DataProcessingController(BatchProcessingService batchProcessingService) { _batchProcessingService = batchProcessingService; } [HttpPost] public IActionResult StartBatchProcessing() { BackgroundJob.Enqueue(() => _batchProcessingService.ProcessLargeDataSet(100, 10000)); return Ok("Batch processing started"); } }

image.png

定时报告生成与邮件发送

这个例子展示了如何使用Hangfire定期生成报告并通过邮件发送。

C#
public interface IEmailService { void SendEmail(string recipient, string subject, string body); } public class EmailService : IEmailService { public void SendEmail(string recipient, string subject, string body) { // send an email Console.WriteLine($"Email sent to {recipient} with subject: {subject}"); } } // Define the IReportGenerator interface public interface IReportGenerator { string GenerateMonthlyReport(); } // Implement the IReportGenerator interface public class ReportGenerator : IReportGenerator { public string GenerateMonthlyReport() { return "This is the monthly report content."; } } // The ReportingService class as defined public class ReportingService { private readonly IEmailService _emailService; private readonly IReportGenerator _reportGenerator; private readonly IBackgroundJobClient _backgroundJobClient; public ReportingService(IEmailService emailService, IReportGenerator reportGenerator, IBackgroundJobClient backgroundJobClient) { _emailService = emailService; _reportGenerator = reportGenerator; _backgroundJobClient = backgroundJobClient; } public void GenerateAndSendMonthlyReport() { var report = _reportGenerator.GenerateMonthlyReport(); var recipients = new[] { "manager@example.com", "director@example.com" }; foreach (var recipient in recipients) { _backgroundJobClient.Enqueue(() => _emailService.SendEmail(recipient, "Monthly Report", report)); } } }
C#
// 在这里设置重复作业 using (var scope = app.Services.CreateScope()) { var recurringJobManager = scope.ServiceProvider.GetRequiredService<IRecurringJobManager>(); recurringJobManager.AddOrUpdate<ReportingService>( "monthly-report", x => x.GenerateAndSendMonthlyReport(), Cron.Monthly(1, 2)); //每月第一天凌晨2点 }

使用Hangfire进行缓存预热

这个例子展示了如何使用Hangfire定期预热应用程序缓存。

C#
public class CacheWarmupService { private readonly IMemoryCache _cache; private readonly IProductRepository _productRepository; public CacheWarmupService(IMemoryCache cache, IProductRepository productRepository) { _cache = cache; _productRepository = productRepository; } public void WarmupProductCache() { var products = _productRepository.GetAllProducts(); foreach (var product in products) { _cache.Set($"product_{product.Id}", product, TimeSpan.FromHours(1)); } Console.WriteLine($"Cache warmed up at {DateTime.Now}"); } } // 注册定时作业 using (var scope = app.Services.CreateScope()) { var recurringJobManager = scope.ServiceProvider.GetRequiredService<IRecurringJobManager>(); recurringJobManager.AddOrUpdate<CacheWarmupService>( "monthly-report", x => x.WarmupProductCache(), Cron.Hourly); }

最佳实践

  1. 使用依赖注入: Hangfire支持依赖注入,利用这一特性来管理服务的生命周期。
  2. 适当的异常处理: 在后台作业中实现适当的异常处理,以确保作业失败时能够正确重试或记录。
  3. 监控和日志: 利用Hangfire的仪表板和日志功能来监控作业执行情况。
  4. 作业幂等性: 设计作业使其具有幂等性,这样即使重复执行也不会产生副作用。
  5. 合理使用重试: 配置合适的重试策略,避免无限重试导致资源浪费。

结论

Hangfire为.NET开发者提供了一个强大而灵活的后台作业处理解决方案。通过本文的示例和最佳实践,你应该能够在自己的C#项目中有效地使用Hangfire来管理各种类型的后台任务。无论是简单的延迟作业还是复杂的重复任务,Hangfire都能满足你的需求,同时保证可靠性和可扩展性。

本文作者:rick

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!