0

0

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

煙雲

煙雲

发布时间:2026-01-02 08:48:39

|

647人浏览过

|

来源于php中文网

原创

在 asp.net core 中注册可取消的后台服务需继承 backgroundservice 基类,重写 executeasync 并全程传递 cancellationtoken;注册时调用 addhostedservice(),避免生命周期冲突,优先使用 periodictimer 实现定时任务。

c# 在asp.net core中管理和取消后台任务

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

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

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

  • 注册时使用 AddHostedService<mybackgroundservice>()</mybackgroundservice>,而非普通 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<ApplicationDbContext>();

        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

版纳武林DIY企业建站系统
版纳武林DIY企业建站系统

系统简介1:安全可靠: 在微软主推的.NET开发平台上,采用业界领先的ASP.NET技术和C#语言开发,不仅安全可靠,并能保证系统的高性能运行。2:简单易用:版纳武林DIY企业建站系统真正做到以人为本、以用户体验为中心,能使您快速搭建您的网站。后台管理操作简单,一目了然,没有夹杂多余的功能和广告。3:布局易改:版纳武林DIY企业建站系统采用的是博客形式的风格管理,让您真正感受到我的地盘听我的.4:

下载
  • 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 调用、每一段同步等待都真正尊重了它——哪怕一个地方漏掉,整个取消链就断了。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

104

2023.09.25

登录token无效
登录token无效

登录token无效解决方法:1、检查token的有效期限,如果token已经过期,需要重新获取一个新的token;2、检查token的签名,如果签名不正确,需要重新获取一个新的token;3、检查密钥的正确性,如果密钥不正确,需要重新获取一个新的token;4、使用HTTPS协议传输token,建议使用HTTPS协议进行传输 ;5、使用双因素认证,双因素认证可以提高账户的安全性。

6511

2023.09.14

登录token无效怎么办
登录token无效怎么办

登录token无效的解决办法有检查Token是否过期、检查Token是否正确、检查Token是否被篡改、检查Token是否与用户匹配、清除缓存或Cookie、检查网络连接和服务器状态、重新登录或请求新的Token、联系技术支持或开发人员等。本专题为大家提供token相关的文章、下载、课程内容,供大家免费下载体验。

840

2023.09.14

token怎么获取
token怎么获取

获取token值的方法:1、小程序调用“wx.login()”获取 临时登录凭证code,并回传到开发者服务器;2、开发者服务器以code换取,用户唯一标识openid和会话密钥“session_key”。想了解更详细的内容,可以阅读本专题下面的文章。

1088

2023.12.21

token什么意思
token什么意思

token是一种用于表示用户权限、记录交易信息、支付虚拟货币的数字货币。可以用来在特定的网络上进行交易,用来购买或出售特定的虚拟货币,也可以用来支付特定的服务费用。想了解更多token什么意思的相关内容可以访问本专题下面的文章。

1802

2024.03.01

Java 并发编程高级实践
Java 并发编程高级实践

本专题深入讲解 Java 在高并发开发中的核心技术,涵盖线程模型、Thread 与 Runnable、Lock 与 synchronized、原子类、并发容器、线程池(Executor 框架)、阻塞队列、并发工具类(CountDownLatch、Semaphore)、以及高并发系统设计中的关键策略。通过实战案例帮助学习者全面掌握构建高性能并发应用的工程能力。

96

2025.12.01

数据库三范式
数据库三范式

数据库三范式是一种设计规范,用于规范化关系型数据库中的数据结构,它通过消除冗余数据、提高数据库性能和数据一致性,提供了一种有效的数据库设计方法。本专题提供数据库三范式相关的文章、下载和课程。

381

2023.06.29

如何删除数据库
如何删除数据库

删除数据库是指在MySQL中完全移除一个数据库及其所包含的所有数据和结构,作用包括:1、释放存储空间;2、确保数据的安全性;3、提高数据库的整体性能,加速查询和操作的执行速度。尽管删除数据库具有一些好处,但在执行任何删除操作之前,务必谨慎操作,并备份重要的数据。删除数据库将永久性地删除所有相关数据和结构,无法回滚。

2105

2023.08.14

Swift iOS架构设计与MVVM模式实战
Swift iOS架构设计与MVVM模式实战

本专题聚焦 Swift 在 iOS 应用架构设计中的实践,系统讲解 MVVM 模式的核心思想、数据绑定机制、模块拆分策略以及组件化开发方法。内容涵盖网络层封装、状态管理、依赖注入与性能优化技巧。通过完整项目案例,帮助开发者构建结构清晰、可维护性强的 iOS 应用架构体系。

3

2026.03.03

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Java 教程
Java 教程

共578课时 | 76.4万人学习

国外Web开发全栈课程全集
国外Web开发全栈课程全集

共12课时 | 1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号