C#的CancellationToken是.NET异步编程体系中用于传递取消请求的核心类型,它配合CancellationTokenSource使用,可以在异步操作执行过程中随时触发取消指令,让正在运行的任务及时终止,避免无效的资源消耗。这种机制在网络请求、文件读写、大量数据计算等耗时场景中非常实用,能够有效提升应用的响应性和资源利用率。

CancellationToken的基本概念
CancellationToken是一个轻量级的值类型,它本身不存储取消状态,而是作为取消通知的载体,由CancellationTokenSource创建并分发到各个需要支持取消的操作中。当CancellationTokenSource触发取消时,所有持有对应CancellationToken的操作都能感知到取消请求,进而执行终止逻辑。
它的核心属性有两个:
- IsCancellationRequested:布尔类型,指示是否已经收到取消请求
- CanBeCanceled:布尔类型,指示当前令牌是否支持取消操作
配套类型CancellationTokenSource
CancellationTokenSource是创建和管理CancellationToken的工厂类型,负责触发取消请求,它的常用属性和方法如下:
| 成员 | 说明 |
|---|---|
| Token | 获取关联的CancellationToken实例 |
| Cancel() | 触发取消请求,通知所有关联的令牌取消 |
| CancelAfter(TimeSpan) | 在指定时间后自动触发取消请求 |
| Dispose() | 释放实例占用的资源 |
实现可取消异步操作的基本步骤
实现可取消的异步操作通常遵循以下流程:
- 创建CancellationTokenSource实例
- 获取对应的CancellationToken传递给异步方法
- 在异步方法内部定期检查CancellationToken的取消状态
- 在需要取消的时候调用CancellationTokenSource的Cancel方法
- 操作结束后释放CancellationTokenSource资源
基础示例:可取消的异步延迟操作
下面是一个简单的示例,模拟一个耗时3秒的异步操作,支持在1秒后取消:
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
// 创建取消令牌源
using CancellationTokenSource cts = new CancellationTokenSource();
// 1秒后自动触发取消
cts.CancelAfter(TimeSpan.FromSeconds(1));
try
{
await LongRunningOperationAsync(cts.Token);
Console.WriteLine("操作正常完成");
}
catch (OperationCanceledException)
{
Console.WriteLine("操作被取消");
}
}
static async Task LongRunningOperationAsync(CancellationToken cancellationToken)
{
Console.WriteLine("开始执行耗时操作");
// 模拟耗时操作,同时传入取消令牌
await Task.Delay(3000, cancellationToken);
Console.WriteLine("耗时操作执行完成");
}
}
运行上述代码后,由于1秒就触发了取消,Task.Delay会抛出OperationCanceledException异常,最终输出操作被取消的提示。
循环操作中的取消实现
如果异步操作内部包含循环逻辑,需要在每次循环时检查取消状态,示例代码如下:
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
using CancellationTokenSource cts = new CancellationTokenSource();
// 2秒后取消
cts.CancelAfter(2000);
try
{
await ProcessLoopAsync(cts.Token);
}
catch (OperationCanceledException)
{
Console.WriteLine("循环操作被取消");
}
}
static async Task ProcessLoopAsync(CancellationToken cancellationToken)
{
for (int i = 0; i < 10; i++)
{
// 检查取消请求
cancellationToken.ThrowIfCancellationRequested();
Console.WriteLine($"处理第 {i + 1} 个任务");
// 模拟单个任务的耗时
await Task.Delay(500, cancellationToken);
}
Console.WriteLine("所有循环任务完成");
}
}
代码中ThrowIfCancellationRequested方法会在收到取消请求时直接抛出OperationCanceledException,也可以在循环内手动判断cancellationToken.IsCancellationRequested属性,执行自定义的收尾逻辑后再退出循环。
多任务场景下的取消传递
当有多个并行任务都需要支持取消时,只需要将同一个CancellationToken传递给所有任务即可,示例代码如下:
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
using CancellationTokenSource cts = new CancellationTokenSource();
// 1.5秒后取消
cts.CancelAfter(1500);
try
{
Task task1 = Task1Async(cts.Token);
Task task2 = Task2Async(cts.Token);
Task task3 = Task3Async(cts.Token);
await Task.WhenAll(task1, task2, task3);
Console.WriteLine("所有任务完成");
}
catch (OperationCanceledException)
{
Console.WriteLine("有任务被取消,所有关联任务将收到取消通知");
}
}
static async Task Task1Async(CancellationToken cancellationToken)
{
await Task.Delay(2000, cancellationToken);
Console.WriteLine("任务1完成");
}
static async Task Task2Async(CancellationToken cancellationToken)
{
await Task.Delay(1000, cancellationToken);
Console.WriteLine("任务2完成");
}
static async Task Task3Async(CancellationToken cancellationToken)
{
await Task.Delay(3000, cancellationToken);
Console.WriteLine("任务3完成");
}
}
上述代码中三个任务共享同一个取消令牌,1.5秒后取消触发,正在运行的三个任务都会收到取消通知并终止。
取消操作的注意事项
- CancellationTokenSource使用完毕后需要及时调用Dispose释放资源,建议使用using语句管理生命周期
- 取消操作是协作式的,只能由操作内部主动检查取消状态并终止,无法从外部强制终止正在运行的任务
- 如果异步方法内部没有检查取消令牌的逻辑,即使传入了CancellationToken,操作也不会响应取消请求
- 除了OperationCanceledException,也可以在捕获异常后判断
cancellationToken.IsCancellationRequested属性,区分是主动取消还是其他异常 - 如果需要在取消时执行额外的清理逻辑,可以在捕获OperationCanceledException后编写对应的处理代码
注册取消回调
CancellationToken还支持注册取消时触发的回调函数,适合需要在取消时执行额外操作的场景:
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
using CancellationTokenSource cts = new CancellationTokenSource();
// 注册取消回调
cts.Token.Register(() =>
{
Console.WriteLine("收到取消通知,执行清理逻辑");
});
// 1秒后取消
cts.CancelAfter(1000);
try
{
await Task.Delay(3000, cts.Token);
}
catch (OperationCanceledException)
{
Console.WriteLine("操作被取消");
}
}
}
运行后会在取消触发时先执行注册的回调方法,再抛出异常,方便开发者执行资源释放、状态重置等清理操作。
CancellationToken异步操作可取消任务C#异步编程修改时间:2026-06-20 16:09:34