前言
在异步编程中,任务取消机制是不可或缺的一部分。随着 .NET Core 对异步编程的全面支持,CancellationToken 成为了控制异步操作生命周期的重要工具。
本文将系统性地讲解 CancellationToken 和 CancellationTokenSource 的基本用法、工作原理以及常见使用场景,帮助大家更好地掌握异步任务的取消机制。
一、CancellationToken 简介
CancellationToken 是 .NET 提供的一个轻量级结构体,用于通知一个或多个线程应该停止当前操作。它本身并不执行取消操作,而是作为一个信号传递机制。
构造函数
public CancellationToken();
// 默认构造函数(不常用)
public CancellationToken(bool canceled);
// 初始化为取消状态或非取消状态
常用属性
| 属性 | 描述 |
|---|---|
None | 获取一个空的 CancellationToken |
CanBeCanceled | 表示是否可以被取消 |
IsCancellationRequested | 表示是否已请求取消 |
WaitHandle | 获取与此令牌关联的 WaitHandle |
注册回调方法
通过 Register 方法可以注册回调函数,在取消时执行:
public CancellationTokenRegistration Register(Action callback);
public CancellationTokenRegistration Register(Action callback, bool useSynchronizationContext);
public CancellationTokenRegistration Register([NullableAttribute(new[] { 1, 2 })] Action<object?> callback, object? state);
public CancellationTokenRegistration Register([NullableAttribute(new[] { 1, 2 })] Action<object?> callback, object? state, bool useSynchronizationContext);
注意:每个注册的回调只会执行一次。
取消注册
通过返回的 CancellationTokenRegistration 可以取消注册:
var registration = token.Register(() => Console.WriteLine("Canceled"));
registration.Unregister();
二、CancellationTokenSource 控制器
CancellationTokenSource 是 CancellationToken 的控制器,通过它来触发取消操作。
创建方式
CancellationTokenSource cts = new CancellationTokenSource();
也可以指定延迟时间自动取消:
cts.CancelAfter(5000); // 5秒后自动取消
主要方法
-
Cancel():立即取消 -
Cancel(bool throwOnFirstException):指定异常处理策略 -
CancelAfter(int millisecondsDelay)/CancelAfter(TimeSpan delay):延迟取消
异常处理行为
当多个回调抛出异常时,可以通过 throwOnFirstException 参数控制处理方式:
-
true:遇到第一个异常立即抛出,后续不再执行。 -
false:收集所有异常并抛出AggregateException。
示例:
try {
cts.Token.Register(() => throw new Exception("1"));
cts.Token.Register(() => throw new Exception("2"));
cts.Cancel(false); // 抛出 AggregateException
} catch (Exception ex) {
// ex is AggregateException: [Exception("2"), Exception("1")]
}
三、CancellationToken 的组合使用
通过 CreateLinkedTokenSource 可以创建一个联动的 CancellationToken:
CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cts1.Token, cts2.Token);
当任意一个源取消时,联动的 CancellationToken 也会被取消。
典型使用场景
场景一:取消异步任务
CancellationTokenSource cts = new CancellationTokenSource();
var task = new Task(() =>
{
Thread.Sleep(1500);
Console.WriteLine("Execute Some Code");
}, cts.Token);
task.Start();
cts.Cancel();
Thread.Sleep(1000);
Console.WriteLine("Task状态:" + task.Status); // Canceled
场景二:资源释放后通知
class Demo
{
CancellationTokenSource cts = new CancellationTokenSource();
public CancellationToken Token => cts.Token;
public void Close()
{
Thread.Sleep(3000);
cts.Cancel(); // 执行通知
}
}
调用方无需关心何时注册回调。
场景三:无限循环任务控制
public CancellationTokenSource Listen()
{
var cts = new CancellationTokenSource();
Task.Run(() =>
{
while (true)
{
cts.Token.ThrowIfCancellationRequested();
Thread.Sleep(1000);
Console.WriteLine("Run");
}
});
return cts;
}
外部可通过 cts.Cancel() 终止循环。
场景四:作为方法参数传递取消信号
static void Main(string[] args)
{
var cts = new CancellationTokenSource();
Method("hello", cts.Token);
cts.Cancel();
}
static void Method(string message, CancellationToken cancellationToken = default)
{
Console.WriteLine($"message:{message}");
cancellationToken.Register(() => Console.WriteLine("complete"));
}
这种方式使方法具备可取消性,且不影响主流程逻辑。
总结
CancellationToken 和 CancellationTokenSource 是 .NET Core 中实现异步任务取消的核心组件。
它们提供一种优雅、可控的方式来管理异步操作的生命周期,尤其适用于需要动态控制任务执行状态的场景。通过合理使用这些组件,可以显著提升代码的响应性和健壮性。
在实际开发中,建议优先使用 CancellationTokenSource 来创建和管理 CancellationToken,并通过 Register 和 ThrowIfCancellationRequested 方法进行精细控制。同时,结合多线程、事件驱动等模式,可以构建更加灵活的应用架构。
关键词
CancellationToken、CancellationTokenSource、异步编程、Task、取消操作、Register、Unregister、ThrowIfCancellationRequested、CreateLinkedTokenSource、异步任务控制
最后
如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。
也可以加入微信公众号 [DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!
优秀是一种习惯,欢迎大家留言学习!
作者: 没有星星的夏季
出处:cnblogs.com/shanfeng1000/p/13402152.html
声明:网络内容,仅供学习,尊重版权,侵权速删,歉意致谢!