如何测量Hangfire作业执行耗时及批量作业完成总时长?
测量Hangfire批量作业总完成时长的方法
这里提供几种实用方案,适合你测试20-40个Hangfire作业的整体完成耗时:
方案一:自定义作业过滤器追踪全局时间
通过Hangfire的过滤器机制,统一追踪这批作业的开始与结束时间,核心是用线程安全的计数器判断所有作业是否完成:
- 创建自定义过滤器类:
public class BatchJobTrackingFilter : JobFilterAttribute, IElectStateFilter { private static int _totalJobs; private static DateTime _batchStartTime; private static int _completedJobs; private static DateTime _batchEndTime; // 初始化批量作业的总数量和开始时间 public static void InitializeBatch(int jobCount) { Interlocked.Exchange(ref _totalJobs, jobCount); Interlocked.Exchange(ref _completedJobs, 0); _batchStartTime = DateTime.UtcNow; _batchEndTime = DateTime.MinValue; } public void OnStateElection(ElectStateContext context) { // 仅处理成功完成的作业 if (context.CandidateState is SucceededState) { var completed = Interlocked.Increment(ref _completedJobs); // 当最后一个作业完成时记录结束时间 if (completed == _totalJobs) { _batchEndTime = DateTime.UtcNow; var totalDuration = _batchEndTime - _batchStartTime; // 这里可将时长输出到日志、控制台或存储 Console.WriteLine($"所有作业完成,总耗时:{totalDuration.TotalSeconds:F2}秒"); } } } }
- 使用方式:
- 启动Hangfire时注册全局过滤器:
GlobalJobFilters.Filters.Add(new BatchJobTrackingFilter()); - 创建作业前调用初始化方法:
BatchJobTrackingFilter.InitializeBatch(30);(假设创建30个作业) - 正常创建所有Hangfire作业,过滤器会自动追踪完成状态
- 启动Hangfire时注册全局过滤器:
方案二:批量标记+定时查询存储
给这批作业添加统一标识,通过查询Hangfire存储判断完成状态,适合不需要全局过滤器的场景:
- 创建作业时添加自定义参数:
var batchId = Guid.NewGuid().ToString(); var totalJobs = 30; var batchStartTime = DateTime.UtcNow; // 创建30个作业,每个携带batchId参数 for (int i = 0; i < totalJobs; i++) { BackgroundJob.Enqueue(() => YourJobMethod(i)).SetJobParameter("BatchId", batchId); }
- 定时查询完成情况:
可以用单独的后台任务或控制台程序定期检查:
var connection = JobStorage.Current.GetConnection(); bool allCompleted = false; while (!allCompleted) { // 查询该批次下成功的作业数量 var succeededJobs = connection.GetJobsByStateName("Succeeded") .Where(job => job.GetJobParameter<string>("BatchId") == batchId) .Count(); if (succeededJobs == totalJobs) { var totalDuration = DateTime.UtcNow - batchStartTime; Console.WriteLine($"所有作业完成,总耗时:{totalDuration.TotalSeconds:F2}秒"); allCompleted = true; } else { // 每隔1秒查询一次,可根据实际调整间隔 Thread.Sleep(1000); } }
方案三:利用Hangfire.Batches扩展(若已使用)
如果项目引入了Hangfire.Batches包,可直接利用批量作业的完成事件:
var batchStartTime = DateTime.UtcNow; // 创建批量作业 var batchId = BatchJob.StartNew(batch => { for (int i = 0; i < 30; i++) { batch.Enqueue(() => YourJobMethod(i)); } }); // 监听批量完成事件 BatchJob.OnBatchSucceeded(batchId, () => { var totalDuration = DateTime.UtcNow - batchStartTime; Console.WriteLine($"批量作业完成,总耗时:{totalDuration.TotalSeconds:F2}秒"); });
注意:若用SQL Server作为Hangfire存储,也可直接通过SQL语句统计特定批次的成功作业数,效率更高。
内容的提问来源于stack exchange,提问作者Ragini
相关产品推荐
相关产品推荐

