0

0

C# CancellationTokenSource的用法 - 如何优雅地取消异步任务

幻夢星雲

幻夢星雲

发布时间:2025-12-05 15:48:31

|

524人浏览过

|

来源于php中文网

原创

CancellationTokenSource 与 CancellationToken 配合实现协作式取消:前者发起取消请求,后者传递并监听信号,异步方法通过轮询或 ThrowIfCancellationRequested 响应,抛出 OperationCanceledException 终止执行。

c# cancellationtokensource的用法 - 如何优雅地取消异步任务

在C#中处理异步操作时,经常需要支持取消功能。比如用户点击“取消”按钮、超时或切换页面时,正在运行的异步任务应能及时停止,避免资源浪费和潜在错误。CancellationTokenSource 正是为此设计的核心机制,它与 CancellationToken 配合使用,实现对异步任务的优雅取消。

1. CancellationToken 和 CancellationTokenSource 的关系

CancellationTokenSource 是取消请求的发起者,通过调用其 Cancel() 方法发出取消通知。而 CancellationToken 是一个轻量结构体,由 CancellationTokenSource 创建并传递给异步方法,用于监听是否收到取消请求。

异步方法通过轮询或注册回调来响应取消令牌,一旦检测到取消信号,就停止执行并抛出 OperationCanceledException,从而实现协作式取消(cooperative cancellation)。

示例代码:

var cts = new CancellationTokenSource();
CancellationToken token = cts.Token;

// 启动异步任务并传入取消令牌
Task.Run(async () =>
{
    try
    {
        await DoWorkAsync(token);
    }
    catch (OperationCanceledException)
    {
        Console.WriteLine("任务已被取消");
    }
}, token);

// 模拟外部触发取消
cts.Cancel(); // 发起取消

2. 在异步方法中响应取消令牌

大多数内置异步方法(如 HttpClient.GetAsync、Stream.ReadAsync 等)都接受 CancellationToken 参数,会自动响应取消请求。在自定义异步逻辑中,需手动检查令牌状态。

常用方式包括:

LobeHub
LobeHub

LobeChat brings you the best user experience of ChatGPT, OLLaMA, Gemini, Claude

下载
  • 将 token 传给支持取消的 API
  • 调用 token.ThrowIfCancellationRequested() 主动抛出异常
  • 在循环中检查 token.IsCancellationRequested
自定义异步方法示例:

private async Task DoWorkAsync(CancellationToken token)
{
    for (int i = 0; i < 100; i++)
    {
        // 模拟耗时操作
        await Task.Delay(100, token); // Delay 支持取消

        // 手动检查(可选)
        if (token.IsCancellationRequested)
        {
            token.ThrowIfCancellationRequested();
        }

        Console.WriteLine($"处理进度: {i + 1}%");
    }
}

3. 设置超时自动取消

CancellationTokenSource 支持在构造时指定超时时间,超时后自动触发取消,无需手动调用 Cancel()。

// 5秒后自动取消
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));

try
{
    await LongRunningOperationAsync(cts.Token);
}
catch (OperationCanceledException)
{
    Console.WriteLine("操作因超时被取消");
}

4. 取消多个任务或组合取消条件

如果需要监听多个取消源,可以使用 CancellationTokenSource.CreateLinkedTokenSource 链接多个令牌。

var cts1 = new CancellationTokenSource();
var cts2 = new CancellationTokenSource();

// 创建联合令牌
using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cts1.Token, cts2.Token);
var token = linkedCts.Token;

// 任意一个源取消,linkedCts 就会触发
await Task.Run(() => DoWorkAsync(token), token);

cts1.Cancel(); // 触发取消

这种模式适用于页面级取消 + 超时取消的场景。

5. 使用注意事项

  • 始终在可能的地方传递 CancellationToken,尤其是 I/O 操作
  • 使用 using 声明或 try-finally 确保 CancellationTokenSource 被释放
  • 捕获 OperationCanceledException 是正常流程,不应视为错误
  • 不要强行终止线程,应依赖协作式取消

基本上就这些。合理使用 CancellationTokenSource 能让异步代码更健壮、响应更快,也能提升用户体验。关键是把取消作为一种协作行为,而不是强制中断。

相关专题

更多
登录token无效
登录token无效

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

6096

2023.09.14

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

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

806

2023.09.14

token怎么获取
token怎么获取

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

1062

2023.12.21

token什么意思
token什么意思

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

1247

2024.03.01

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

196

2025.06.09

golang结构体方法
golang结构体方法

本专题整合了golang结构体相关内容,请阅读专题下面的文章了解更多。

189

2025.07.04

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

481

2023.08.10

高德地图升级方法汇总
高德地图升级方法汇总

本专题整合了高德地图升级相关教程,阅读专题下面的文章了解更多详细内容。

65

2026.01.16

全民K歌得高分教程大全
全民K歌得高分教程大全

本专题整合了全民K歌得高分技巧汇总,阅读专题下面的文章了解更多详细内容。

121

2026.01.16

热门下载

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

精品课程

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

共32课时 | 3.9万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.8万人学习

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

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