当前位置: 首页 > news >正文

Asp .Net Core 系列:Asp .Net Core 集成 Hangfire+MySQL

在 .NET 或 .NET Core 应用中,若需在不依赖 Windows 服务、独立进程的前提下实现后台处理,Hangfire 是最成熟、简单的方案之一 —— 它可直接嵌入现有应用(如 ASP.NET Core Web 应用),无需额外部署,同时提供任务持久化、监控和重试能力。以下从 核心优势、快速集成步骤、关键用法 三方面,梳理如何用 Hangfire 实现后台处理:

一、为什么选择 Hangfire(核心优势)

  1. 零额外部署:可直接嵌入 Web 应用、控制台应用,无需单独部署 Windows 服务或计划任务;
  2. 任务持久化:支持 SQL Server、MySQL、Redis 等存储,应用重启后未执行的任务不会丢失;
  3. 可视化监控:自带 Dashboard 控制台,可实时查看任务状态(成功 / 失败 / 排队)、执行日志、重试记录;
  4. 多任务类型支持:覆盖常见后台场景(一次性任务、定时任务、周期性任务);
  5. 高可靠性:自动重试失败任务,支持任务优先级(队列区分),避免单点故障。
Install-Package Hangfire.AspNetCore
Install-Package Hangfire.MySqlStorage
    #region Hangfire与MySQLstring connString = configuration.GetConnectionString("Hangfire")?? throw new ArgumentException("未找到Hangfire连接字符串");context.Services.AddHangfire(config =>{config.SetDataCompatibilityLevel(CompatibilityLevel.Version_180).UseSimpleAssemblyNameTypeSerializer().UseRecommendedSerializerSettings();config.UseStorage(new MySqlStorage(connString, new MySqlStorageOptions()));});context.Services.AddHangfireServer();context.Services.AddTransient<IBackgroundJobClient, BackgroundJobClient>();#endregion#region 定义Queuescontext.Services.AddHangfireServer(options =>{options.Queues = new[] { "maintenance-plan-overtime" };options.WorkerCount = 1;});#endregion
}public override async Task OnApplicationInitializationAsync(
ApplicationInitializationContext context)
{await context.AddBackgroundWorkerAsync<LimitRecordWorker>();
}public override Task OnPostApplicationInitializationAsync(ApplicationInitializationContext context)
{const string NAME = "HangfirePeriodicBackgroundWorkerAdapter<BackgroundJobWorker>.DoWorkAsync";RecurringJob.RemoveIfExists(NAME);return base.OnPostApplicationInitializationAsync(context);
}

如果你想使用 Hangfire Dashboard 来查看和管理后台任务,你需要在 Configure 方法中添加相应的中间件:

app.UseHangfireDashboard();

定时任务:

public class LimitRecordWorker : HangfireBackgroundWorkerBase
{private readonly IAbpDistributedLock _distributedLock;private readonly IUnitOfWorkManager _unitOfWorkManager;private readonly IBackgroundJobManager _backgroundJobManager;public LimitRecordWorker(IAbpDistributedLock distributedLock,IUnitOfWorkManager unitOfWorkManager,IConfiguration configuration,IBackgroundJobManager backgroundJobManager){_distributedLock = distributedLock;_unitOfWorkManager = unitOfWorkManager;RecurringJobId = nameof(LimitRecordWorker);_backgroundJobManager = backgroundJobManager;CronExpression = configuration["Crons:LimitRecordCron"];}public override async Task DoWorkAsync(CancellationToken cancellationToken = default){await using (var handle = await _distributedLock.TryAcquireAsync("LimitRecordDistributedLock", TimeSpan.FromSeconds(10))){if (handle != null){using (var uow = LazyServiceProvider.LazyGetRequiredService<IUnitOfWorkManager>().Begin()){Log.Information("LimitRecordWorker" + DateTime.Now);for (int i = 0; i <= 5; i++){MaintenancePlanOverTimeArgs workProcedureLeaderArgs = new MaintenancePlanOverTimeArgs();workProcedureLeaderArgs.Serial = i;await _backgroundJobManager.EnqueueAsync(workProcedureLeaderArgs, delay: TimeSpan.FromHours(workProcedureLeaderArgs.OverTime % 24));}await uow.CompleteAsync();}}}}
}

队列服务:

[Queue("maintenance-plan-overtime")]public class MaintenancePlanOverTimeJob : AsyncBackgroundJob<MaintenancePlanOverTimeArgs>, ITransientDependency{public MaintenancePlanOverTimeJob(){}public override async Task ExecuteAsync(MaintenancePlanOverTimeArgs args){Log.Information("MaintenancePlanOverTimeJob:" + args.Serial + "--" + DateTime.Now);}}public class MaintenancePlanOverTimeArgs{public int Serial { get; set; }public List<Guid> EmployeeIds { get; set; }public Guid DepartmentId { get; set; }public Guid? WorkProcedureId { get; set; }public Guid? DeviceDetailTypeId { get; set; }public double OverTime { get; set; }}

效果:


文章转载自:

http://E5dsK03v.qjxkx.cn
http://Vd3ucGaY.qjxkx.cn
http://vLUNRRYK.qjxkx.cn
http://6nVTlVa7.qjxkx.cn
http://FxAbczYD.qjxkx.cn
http://48ZscGha.qjxkx.cn
http://xASTBpAG.qjxkx.cn
http://ySNbHrK8.qjxkx.cn
http://8jadt7qP.qjxkx.cn
http://2PXACSrF.qjxkx.cn
http://fa3XwAs0.qjxkx.cn
http://GIM2zvvq.qjxkx.cn
http://TcqcvFv1.qjxkx.cn
http://NcUzsHMu.qjxkx.cn
http://rbfvSozB.qjxkx.cn
http://cwNb4aTL.qjxkx.cn
http://jBWWWGii.qjxkx.cn
http://Vg9kFfbR.qjxkx.cn
http://zHtWUenW.qjxkx.cn
http://jzLDT4ID.qjxkx.cn
http://zYjnKAn1.qjxkx.cn
http://3JwBFZu4.qjxkx.cn
http://6bwjVwMi.qjxkx.cn
http://wBJbZqQa.qjxkx.cn
http://2TfQCt1G.qjxkx.cn
http://UCcObUmP.qjxkx.cn
http://t3xOLFrD.qjxkx.cn
http://SUJK6Wzi.qjxkx.cn
http://2ABVRHHP.qjxkx.cn
http://KXYyiK1W.qjxkx.cn
http://www.dtcms.com/a/376010.html

相关文章:

  • 如果服务端有数据更新,浏览器缓存同时也没有过期,如何直接使用最新的数据
  • 使用java编写一个基础的彩票抽奖程序
  • 算法题 Day5---String类
  • 【靶场练习】--DVWA第二关Command Injection(命令执行)全难度分析
  • 什么是Adobe Analytics?数据驱动营销的关键工具​
  • 使用Docker搭建MaxKB智能体平台
  • 【链表】3.重排链表(medium)
  • 免费!离线!免安装!Windows文件夹隐藏工具
  • 联邦学习及其相关创新SCI辅导
  • 466章:Python Web爬虫入门:使用Requests和BeautifulSoup
  • ES8集群部署与使用-zookeeper集群部署与使用
  • Nginx 优化与防盗链配置指南
  • 【数据结构】栈详解
  • 力扣周赛困难-3677. 统计二进制回文数字的数目(需要一定推理的经典二分)
  • 【硬件-笔试面试题-77】硬件/电子工程师,笔试面试题(知识点:滤波电路中截止频率的计算)
  • CUDA编程13 - 测量每个Block的执行时间
  • 仓颉编程语言青少年基础教程:特殊数据类型Unit类型和Nothing类型)
  • AFSim2.9.0学习笔记 —— 3、Wizard平台类型与ArkSIM平台介绍
  • 基于LTE标准的MIMO-OFDM仿真程序
  • 814章:Python Web爬虫入门:使用Requests和BeautifulSoup
  • 硬件开发(5)—ARM汇编
  • leetcode16(盛最多水的容器)
  • 《面向高速三维表面成像的微型深度学习轮廓术》论文总结
  • 基于Java的图书管理系统的设计与实现
  • 【Qt跬步积累】—— 初识Qt
  • 第十九章 使用LAMP架构部署动态网站环境
  • 谷歌nano banana官方Prompt模板发布,解锁六大图像生成风格
  • 转载:VSCODE 关闭文件和资源管理器关联
  • Windows 常用命令使用说明
  • Win_Server远程桌面(RDP)服务调用GPU并提上传输帧率和USB设备重定向