导读:本期聚焦于小伙伴创作的《c# CancellationToken 的用法 c#如何取消一个异步任务》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《c# CancellationToken 的用法 c#如何取消一个异步任务》有用,将其分享出去将是对创作者最好的鼓励。

在c#的异步编程场景中,很多时候我们需要在执行耗时异步任务时支持中途取消的能力,比如用户主动终止操作、超时自动取消等,CancellationToken就是专门用于传递取消请求的类型,配合Task相关API可以实现异步任务的优雅取消。

c# CancellationToken 的用法 c#如何取消一个异步任务

CancellationToken核心相关类型

使用CancellationToken取消异步任务,需要了解两个核心类型:

  • CancellationTokenSource:用于创建取消请求,管理取消状态,它可以触发取消操作,并且可以关联取消的回调和超时设置。
  • CancellationToken:用于传递给异步方法,异步方法通过它检查是否收到了取消请求,本身不负责触发取消,只是传递取消信号。

基础用法:取消一个简单异步任务

下面通过一个示例演示如何创建取消请求,传递给异步任务,然后在外部触发取消,让异步任务停止执行。

using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        // 创建CancellationTokenSource实例
        using var cts = new CancellationTokenSource();
        // 启动异步任务,传入CancellationToken
        Task asyncTask = DoWorkAsync(cts.Token);
        
        // 模拟等待1秒后触发取消
        await Task.Delay(1000);
        Console.WriteLine("触发取消请求");
        cts.Cancel();
        
        try
        {
            await asyncTask;
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("异步任务已被取消");
        }
    }
    
    static async Task DoWorkAsync(CancellationToken token)
    {
        for (int i = 0; i < 10; i++)
        {
            // 检查是否收到取消请求
            token.ThrowIfCancellationRequested();
            Console.WriteLine($"执行第{i + 1}次操作");
            await Task.Delay(500, token); // 传入token,让Delay也支持取消
        }
    }
}

上面的代码中,CancellationToken.ThrowIfCancellationRequested()方法会在收到取消请求时抛出OperationCanceledException异常,终止当前任务的执行。同时Task.Delay也传入了token,这样如果取消请求在延迟期间触发,延迟会直接结束,不会继续等待。

带超时的取消场景

很多时候我们需要异步任务执行超过一定时间后自动取消,不需要手动触发,这时候可以使用CancellationTokenSource的超时构造函数。

using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        // 创建超时时间为2秒的CancellationTokenSource
        using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(2));
        try
        {
            await LongRunWorkAsync(cts.Token);
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("任务因超时被取消");
        }
    }
    
    static async Task LongRunWorkAsync(CancellationToken token)
    {
        while (true)
        {
            token.ThrowIfCancellationRequested();
            Console.WriteLine("任务执行中...");
            await Task.Delay(300, token);
        }
    }
}

注册取消回调

当取消请求触发时,我们可能需要执行一些清理操作,比如释放资源、更新状态等,这时候可以通过CancellationToken.Register方法注册回调。

using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        using var cts = new CancellationTokenSource();
        // 注册取消回调
        cts.Token.Register(() =>
        {
            Console.WriteLine("收到取消请求,执行清理操作");
        });
        
        Task task = DoWorkWithCleanupAsync(cts.Token);
        await Task.Delay(800);
        cts.Cancel();
        
        try
        {
            await task;
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("任务已取消");
        }
    }
    
    static async Task DoWorkWithCleanupAsync(CancellationToken token)
    {
        for (int i = 0; i < 5; i++)
        {
            token.ThrowIfCancellationRequested();
            Console.WriteLine($"执行步骤{i + 1}");
            await Task.Delay(400, token);
        }
    }
}

使用注意事项

  • CancellationTokenSource实现了IDisposable接口,使用完毕后应该及时释放,避免资源泄漏,建议使用using语句管理它的生命周期。
  • 不要在异步方法中捕获OperationCanceledException后不做处理直接吞掉异常,除非你明确知道不需要向上传播取消信号,否则应该让异常正常抛出,让上层知道任务被取消了。
  • 如果一个异步方法接收了CancellationToken参数,就应该尽可能在方法内部的所有异步操作中传递这个token,保证整个调用链的取消能力是连贯的。
  • 取消请求是协作式的,也就是说只有异步方法主动检查CancellationToken的状态,取消才会生效,无法强制终止一个不检查取消信号的异步任务。

常见问题解答

为什么取消时会抛出OperationCanceledException?

这是c#异步取消的标准设计,通过异常的方式传播取消信号,可以让取消逻辑和正常的业务逻辑分离,上层调用者可以通过捕获这个特定异常来处理取消后的逻辑,而不需要在每个方法里返回取消状态。

多个异步任务可以共用同一个CancellationToken吗?

可以,多个异步任务可以接收同一个CancellationToken,当取消请求触发时,所有关联的任务都会收到取消信号,适合需要批量取消多个相关任务的场景。

CancellationToken异步任务Taskcsharp取消操作修改时间:2026-07-07 20:33:26

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。