当前位置:首页 > C# > 正文

C#取消令牌详解(CancellationToken注册与注销完整教程)

在 C# 开发中,尤其是处理异步任务、长时间运行的操作或响应用户取消请求时,C#取消令牌CancellationToken)是一个非常重要的工具。它允许我们优雅地通知正在运行的任务:用户希望取消操作。本文将从零开始,手把手教你如何注册注销取消令牌,确保你的程序更加健壮、响应迅速。

C#取消令牌详解(CancellationToken注册与注销完整教程) C#取消令牌  CancellationToken注册 取消令牌注销 异步任务取消 第1张

什么是 CancellationToken?

CancellationToken 是 .NET 提供的一个结构体,用于向一个或多个侦听器发出信号:某个操作应被取消。它通常与 CancellationTokenSource 配合使用——后者负责创建令牌并触发取消。

基本用法:创建与触发取消

首先,我们来看一个最简单的例子:

using System;using System.Threading;using System.Threading.Tasks;class Program{    static async Task Main(string[] args)    {        // 创建一个 CancellationTokenSource        var cts = new CancellationTokenSource();        // 获取取消令牌        CancellationToken token = cts.Token;        // 启动一个异步任务,并传入 token        Task task = DoWorkAsync(token);        // 模拟用户在2秒后请求取消        await Task.Delay(2000);        cts.Cancel(); // 触发取消        try        {            await task;        }        catch (OperationCanceledException)        {            Console.WriteLine("任务已被取消。");        }    }    static async Task DoWorkAsync(CancellationToken token)    {        for (int i = 0; i < 100; i++)        {            // 检查是否请求取消            token.ThrowIfCancellationRequested();            await Task.Delay(100, token); // 支持取消的延迟            Console.WriteLine($"进度: {i + 1}%");        }    }}

注册取消回调(Register)

除了在代码中主动检查 IsCancellationRequested 或调用 ThrowIfCancellationRequested(),你还可以通过 token.Register() 方法注册一个回调函数。当取消发生时,该回调会自动执行。

这在清理资源、记录日志或通知 UI 线程时非常有用。

var cts = new CancellationTokenSource();CancellationToken token = cts.Token;// 注册取消回调CancellationTokenRegistration registration = token.Register(() =>{    Console.WriteLine("取消已触发!正在执行清理操作...");    // 这里可以释放文件句柄、关闭网络连接等});// 启动任务Task.Run(async () =>{    await Task.Delay(3000);    cts.Cancel();});// 模拟等待await Task.Delay(5000);// 注意:registration 本身也需要被正确处理

注销取消回调(Unregister)

当你注册了一个回调后,有时你可能希望在特定条件下取消这个回调的注册,避免它在不再需要时被执行。这就是“注销”操作。

调用 Register() 会返回一个 CancellationTokenRegistration 结构体,你可以调用它的 Dispose() 方法来注销回调。

var cts = new CancellationTokenSource();CancellationToken token = cts.Token;// 注册回调CancellationTokenRegistration registration = token.Register(() =>{    Console.WriteLine("这个回调不应该被执行!");});// 在取消前注销回调registration.Dispose(); // 或 using (registration) { ... }// 触发取消cts.Cancel();// 此时,上面的回调不会执行!

注意:CancellationTokenRegistration 实现了 IDisposable,因此推荐使用 using 语句来自动管理其生命周期:

using (token.Register(CleanupResources)){    // 执行一些可能被取消的操作    await DoSomethingAsync(token);}// 退出 using 块时,自动注销回调void CleanupResources(){    Console.WriteLine("清理资源");}

常见误区与最佳实践

  • 不要重复调用 cts.Cancel() —— 它是幂等的,但无意义。
  • 始终在支持取消的方法(如 Task.DelayHttpClient.GetAsync)中传入 CancellationToken
  • 注册的回调会在取消时在某个线程上执行,避免在回调中做耗时操作。
  • 记得释放 CancellationTokenSourceCancellationTokenRegistration,防止内存泄漏。

总结

通过本文,你应该已经掌握了 C#取消令牌 的核心概念,包括如何使用 CancellationTokenSource 创建令牌、如何在异步任务中响应取消请求、如何注册取消回调以及如何安全地注销这些回调。合理使用 异步任务取消机制,能让你的应用更高效、更用户友好。

记住:良好的取消处理不仅是功能需求,更是专业开发的体现。希望这篇关于 CancellationToken注册取消令牌注销 的教程对你有所帮助!