全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

c# 在ASP.NET Core中管理和取消后台任务

在 ASP.NET Core 中注册可取消的后台服务需继承 BackgroundService 基类,重写 ExecuteAsync 并全程传递 CancellationToken;注册时调用 AddHostedService(),避免生命周期冲突,优先使用 PeriodicTimer 实现定时任务。

如何在 ASP.NET Core 中注册可取消的后台服务

ASP.NET Core 的 IHostedService 是管理长时运行后台任务的标准方式,但原生不自动传递取消信号——必须显式接收 CancellationToken 并在关键阻塞点响应它。直接在 ExecuteAsync 中忽略 cancellationToken 参数,会导致应用关闭时任务强行终止,可能丢失数据或破坏状态。

正确做法是将传入的 CancellationToken 透传给所有支持它的异步 API(如 Task.DelayHttpClient.GetAsync),并在非托管等待(如 Thread.Sleep)前手动检查 IsCancellationRequested

  • 注册时使用 AddHostedService(),而非普通 AddSingleton
  • 构造函数中不要捕获 IServiceProvider 来解析服务——可能引发作用域生命周期冲突;改用 IServiceScopeFactory 按需创建作用域
  • 若任务需定期执行,优先用 PeriodicTimer(.NET 6+)替代 Task.Delay 循环,它原生支持 CancellationToken
public class DataSyncService : IHostedService, IDisposable
{
    private readonly IServiceScopeFactory _scopeFactory;
    private Timer? _timer;

    public DataSyncService(IServiceScopeFactory scopeFactory)
    {
        _scopeFactory = scopeFactory;
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromMinutes(5));
        return Task.CompletedTask;
    }

    private async void DoWork(object? state)
    {
        using var scope = _scopeFactory.CreateScope();
        var dbContext = scope.ServiceProvider.GetRequiredService();

        try
        {
            await dbContext.SyncDataAsync(cancellationToken); // 假设该方法接受 token
        }
        catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
        {
            // 正常退出,不记录错误
        }
        catch (Exception ex)
        {
            // 记录未预期异常
        }
    }

    public async Task StopAsync(CancellationToken cancellationToken)
    {
        _timer?.Change(Timeout.Infinite, 0);
        _timer?.Dispose();
        await Task.Delay(100, cancellationToken); // 给正在执行的 DoWork 留出收尾时间
    }

    public void Dispose() => _timer?.Dispose();
}

为什么 BackgroundService 基类比裸实现 IHostedService 更安全

BackgroundService 是微软提供的抽象基类,它封装了启动/停止协调逻辑,并确保 StopAsync 被调用后,正在运行的 ExecuteAsync 任务能自然完成(除非超时)。裸写 IHostedService 容易漏掉对 cancellationToken 的传播,或在 StopAsync 中过早释放资源,导致 ObjectDisposedException

  • BackgroundServiceStopAsync 默认等待 ExecuteAsync 返回,且会把宿主的 cancellationToken 传入其中
  • ExecuteAsync 内部有长时间无响应的同步操作(如文件锁、外部 API 同步调用),仍需自行添加超时和中断逻辑
  • 不要在 ExecuteAsync 中用 while (true) + await Task.Delay 无限循环——应改为 while (!stoppingToken.IsCancellationRequested)

常见取消失败场景及修复方式

即使用了 CancellationToken,后台任务仍可能无法及时响应取消,典型表现是应用关闭后进程卡住几秒甚至几十秒才退出。根本原因通常是某处阻塞操作没受 token 控制。

  • HttpClient 请求未传入 token:必须用 GetAsync(uri, cancellationToken),不能只用 GetAsync(uri)
  • 数据库查询未启用取消:EF Core 的 ToListAsync(cancellationToken) 和 Dapper 的 QueryAsync(..., cancellationToken) 都需显式传参
  • 自定义同步等待未检查 token:例如 while (!token.IsCancellationRequested) { Thread.Sleep(100); } 应改为 await Task.Delay(100, token)
  • 第三方 SDK 不支持 token:需包裹在 Task.Run(() => { ... }, cancellationToken) 中,并在内部定期轮询 token.IsCancellationRequested

如何测试后台服务的取消行为

本地调试时,Ctrl+C 或发送 SIGTERM 信号即可触发取消流程,但自动化测试需模拟宿主生命周期。不要直接 new 实例并调用 StartAsync——缺少 IHostApplicationLifetime 支持,StopAsync 不会被自动调用。

  • 使用 Host.CreateDefaultBuilder() 构建测试宿主,注入你的服务,再调用 host.StopAsync()
  • 在测试中用 Task.Delay(100).Wait(cancellationToken) 模拟耗时操作,并验证是否在指定时间内完成
  • 注意:BackgroundService 的默认超时是 5 秒(由 HostOptions.ShutdownTimeout 控制),测试时可临时缩短它以便快速验证

真正难的不是加 cancellationToken,而是确认每一个 await 点、每一次 IO 调用、每一段同步等待都真正尊重了它——哪怕一个地方漏掉,整个取消链就断了。


# app  # ai  # 微软  # c#  # 作用域  # .net  # 为什么  # red  # while  # 封装  # 构造函数  # Token  # 循环  # 继承  # Thread  # 异步  # 数据库  # 自动化  # 并在  # 可取消  # 长时间  # 时间内  # 用了  # 自定义  # 重写  # 不支持  # 会把 


相关文章: 盐城做公司网站,江苏电子版退休证办理流程?  如何优化Golang Web性能_Golang HTTP服务器性能提升方法  建站之星展会模板:智能建站与自助搭建高效解决方案  如何自定义建站之星网站的导航菜单样式?  北京制作网站的公司排名,北京三快科技有限公司是做什么?北京三快科技?  建站之星价格显示格式升级,你的预算足够吗?  免费网站制作模板下载,除了易企秀之外还有什么H5平台可以制作H5长页面,最好是免费的?  制作表格网站有哪些,线上表格怎么弄?  如何快速搭建支持数据库操作的智能建站平台?  建站主机服务器选型指南与性能优化方案解析  建站VPS选购需注意哪些关键参数?  公司门户网站制作公司有哪些,怎样使用wordpress制作一个企业网站?  如何快速搭建二级域名独立网站?  如何用免费手机建站系统零基础打造专业网站?  如何选择可靠的免备案建站服务器?  javascript中对象的定义、使用以及对象和原型链操作小结  如何在阿里云虚拟机上搭建网站?步骤解析与避坑指南  宝盒自助建站智能生成技巧:SEO优化与关键词设置指南  如何在万网开始建站?分步指南解析  如何高效利用200m空间完成建站?  如何在沈阳梯子盘古建站优化SEO排名与功能模块?  武汉网站设计制作公司,武汉有哪些比较大的同城网站或论坛,就是里面都是武汉人的?  测试制作网站有哪些,测试性取向的权威测试或者网站?  制作网站的软件免费下载,免费制作app哪个平台好?  如何用PHP工具快速搭建高效网站?  如何在腾讯云服务器快速搭建个人网站?  怎么制作一个起泡网,水泡粪全漏粪育肥舍冬季氨气超过25ppm,可以有哪些措施降低舍内氨气水平?  中山网站推广排名,中山信息港登录入口?  网站制作需要会哪些技术,建立一个网站要花费多少?  在线制作视频网站免费,都有哪些好的动漫网站?  实例解析Array和String方法  相册网站制作软件,图片上的网址怎么复制?  如何用虚拟主机快速搭建网站?详细步骤解析  ,制作一个手机app网站要多少钱?  香港服务器建站指南:免备案优势与SEO优化技巧全解析  制作网站的网址是什么,请问后缀为.com和.com.cn还有.cn的这三种网站是分别是什么类型的网站?  建站之星如何一键生成手机站?  建站org新手必看:2024最新搭建流程与模板选择技巧  山东云建站价格为何差异显著?  网站制作免费,什么网站能看正片电影?  企业网站制作费用多少,企业网站空间一般需要多大,费用是多少?  网站海报制作教学视频教程,有什么免费的高清可商用图片网站,用于海报设计?  PHP 500报错的快速解决方法  网站制作中优化长尾关键字挖掘的技巧,建一个视频网站需要多少钱?  如何确保西部建站助手FTP传输的安全性?  网站制作软件免费下载安装,有哪些免费下载的软件网站?  香港服务器WordPress建站指南:SEO优化与高效部署策略  家族网站制作贴纸教程视频,用豆子做粘帖画怎么制作?  如何制作网站标识牌,动态网站如何制作(教程)?  建站之星安全性能如何?防护体系能否抵御黑客入侵? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。