带数据库连接的Fire and Forget模式与Hangfire该如何选型?
现有后台任务方案可行性及是否需切换至Hangfire
我们有一批需在网关执行的任务,用户发起的新排队任务会写入数据库,由BackgroundService每30秒触发并执行RunJobManager()方法:
public async Task RunJobManager() { // This context is in the scope of the JobManager // Get a list of IDs of only gateways with an active job var gatewaysWithActiveJob = _context.Gateways .Where(g => g.Type == GatewayType.Owa4x) .Include(g => g.Jobs) .Where(_gatewayHasActiveJob) .Where(_jobIsNotStarted) .ToList(); foreach (var gateway in gatewaysWithActiveJob) { _ = Task.Run(() => ExecuteActiveJobAsync(gateway.Id)); gateway.GetMostRecentJob().JobExectionDate = DateTime.Now; } _context.Gateways.UpdateRange(gatewaysWithActiveJob); await _context.SaveChangesAsync(); }
我们采用Fire and Forget模式触发任务,不等待任务完成就告知数据库任务已启动,原因是部分任务(如向网关上传文件)耗时数分钟,若阻塞会影响用户体验。每个任务线程拥有独立数据库上下文,可更新任务的错误或完成状态:
private async Task ExecuteActiveJobAsync(Guid gatewayId) { // Caution: do not use members other than the scopeFactory as each thread shall have its own scope using (var scope = _serviceScopeFactory.CreateScope()) { await using var scopedContext = scope.ServiceProvider.GetRequiredService<SuncarContext>(); // Below: Task that will be done in this job } }
该方案并非完全“遗忘”任务,仅在系统重启时可能丢失任务,我们会在BackgroundService初始化时重新排队未完成的已启动任务。
近期同事提出不应使用Fire and Forget模式,建议改用Hangfire。我知道Hangfire针对后台任务做了优化,但这种基于后台服务、带数据库连接的无等待线程方案是否可行?是否需要切换到Hangfire?
内容的提问来源于stack exchange,提问作者Rafael Eberle
相关产品推荐
相关产品推荐

