如何在ASP.NET Core中借助Hangfire触发每日汇总邮件发送任务
嘿,我来帮你梳理几种在ASP.NET Core里触发每日汇总邮件任务的可行方案,都是实际项目里常用的:
方案一:用ASP.NET Core原生Hosted Service(后台定时任务)
这是最轻量化的方案,不需要额外依赖,适合简单的每日定时场景。核心思路是创建一个后台服务,让它定期调用你的SendAllSummaries方法。
首先创建一个继承自BackgroundService的类:
public class DailySummaryHostedService : BackgroundService { private readonly IServiceProvider _serviceProvider; private readonly ILogger<DailySummaryHostedService> _logger; public DailySummaryHostedService(IServiceProvider serviceProvider, ILogger<DailySummaryHostedService> logger) { _serviceProvider = serviceProvider; _logger = logger; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { _logger.LogInformation("每日汇总邮件后台服务已启动"); while (!stoppingToken.IsCancellationRequested) { try { // 因为你的SummaryEmailBusiness依赖Scoped服务(比如DbContext),所以要创建服务范围 using (var scope = _serviceProvider.CreateScope()) { var summaryBiz = scope.ServiceProvider.GetRequiredService<SummaryEmailBusiness>(); summaryBiz.SendAllSummaries(); _logger.LogInformation("今日汇总邮件已全部发送"); } } catch (Exception ex) { _logger.LogError(ex, "发送汇总邮件时出现错误"); } // 计算到下一次执行的延迟(比如每天凌晨2点执行,避免时间漂移) var nextRunTime = GetNextScheduledTime(); var delay = nextRunTime - DateTime.Now; await Task.Delay(delay, stoppingToken); } _logger.LogInformation("每日汇总邮件后台服务已停止"); } // 自定义方法:获取下一次执行的时间(比如每天凌晨2点) private DateTime GetNextScheduledTime() { var now = DateTime.Now; var nextRun = new DateTime(now.Year, now.Month, now.Day, 2, 0, 0); // 如果当前时间已经过了2点,就推迟到第二天的2点 if (nextRun <= now) { nextRun = nextRun.AddDays(1); } return nextRun; } }
然后在ConfigureServices里注册这个后台服务:
services.AddHostedService<DailySummaryHostedService>();
方案二:用Hangfire(强大的任务调度框架)
如果你的需求更复杂——比如需要任务重试、可视化管理、支持Cron表达式的灵活调度,那Hangfire是个很棒的选择。
步骤如下:
先安装必要的NuGet包:
Install-Package Hangfire.AspNetCore Install-Package Hangfire.SqlServer // 如果你用SQL Server存储任务数据在
ConfigureServices里配置Hangfire:services.AddHangfire(config => config.UseSqlServerStorage(Configuration.GetConnectionString("DefaultConnection"))); services.AddHangfireServer();(可选)在
Configure里启用Hangfire仪表盘,方便你查看和管理任务:app.UseHangfireDashboard("/hangfire"); // 访问路径可以自定义注册每日定时任务,比如在
Program.cs的应用启动后添加:// 每天凌晨2点执行,Cron表达式"0 0 2 * * ?"表示每天2点0分0秒触发 RecurringJob.AddOrUpdate<SummaryEmailBusiness>( biz => biz.SendAllSummaries(), "0 0 2 * * ?", TimeZoneInfo.Local);
Hangfire会自动处理依赖注入,还自带失败重试、任务日志等功能,非常省心。
方案三:用外部调度工具触发(Cron/Windows任务计划)
如果不想把调度逻辑放在应用内部,或者你的应用不是长期运行的(比如服务器会定期重启),可以写一个API接口,然后用外部工具定时调用它。
首先创建一个API控制器:
[ApiController] [Route("api/summary")] public class SummaryController : ControllerBase { private readonly SummaryEmailBusiness _summaryBiz; public SummaryController(SummaryEmailBusiness summaryBiz) { _summaryBiz = summaryBiz; } [HttpPost("send-all")] public IActionResult TriggerSendAll() { _summaryBiz.SendAllSummaries(); return Ok("汇总邮件发送任务已启动"); } }
然后用外部工具定时调用这个接口:
- Linux系统:编辑Cron任务,添加一行(每天凌晨2点调用):
0 2 * * * curl -X POST https://your-app-domain/api/summary/send-all - Windows系统:打开「任务计划程序」,创建一个定时任务,每天凌晨2点执行PowerShell命令:
Invoke-RestMethod -Uri "https://your-app-domain/api/summary/send-all" -Method Post
最后给你个选型参考:
- 只是简单的每日定时,选Hosted Service就行,原生无依赖;
- 需要复杂调度、任务管理,选Hangfire;
- 想把调度和应用彻底分离,或者应用不长期运行,选外部调度工具。
内容的提问来源于stack exchange,提问作者Guerrilla
相关产品推荐
相关产品推荐

