前言
在程序开发中异步编程和任务管理是确保高效、响应式用户体验的关键。C# 提供强大的工具来处理这些需求,其中 Task
和 CancellationTokenSource
是两个非常重要的组件。Task
用于管理和协调异步操作,而 CancellationTokenSource
则提供优雅的方式来取消或中断这些操作。
在.NET中,CancellationTokenSource、CancellationToken和Task是处理异步操作和取消任务的重要工具。本文将通过一些简单的例子,帮助大家理解它们的用法和协作方式。
正文
CancellationTokenSource
CancellationTokenSource是 C# 中用于生成和管理 CancellationToken 的类,它充当取消操作的触发器。
通过 CancellationTokenSource
,开发者可以控制取消信号的发出,并将这些信号传递给多个异步任务或长时间运行的操作,以便它们能够响应取消请求并优雅地终止。
常用属性和方法
属性
Token: 返回与此源关联的 CancellationToken
。每个 CancellationTokenSource
实例都可以生成一个唯一的 CancellationToken
,该令牌可以传递给多个消费者以监听取消事件。
方法
Cancel(): 触发取消操作。调用此方法后,所有与该 CancellationTokenSource
关联的 CancellationToken
将进入已取消状态,通知所有监听者执行取消逻辑。
CancelAfter(int millisecondsDelay): 设置一个计时器,在指定的毫秒数后自动触发取消操作。这对于设置超时非常有用,确保长时间运行的任务不会无限期挂起。
Dispose(): 释放由 CancellationTokenSource
占用的资源。调用此方法后,不能再使用该实例触发取消操作。建议在不再需要 CancellationTokenSource
时调用 Dispose()
,以避免资源泄漏。
示例
var cts = new CancellationTokenSource();
CancellationToken token = cts.Token;
Task.Run(() => {
for (int i = 0; i < 10; i++)
{
if (token.IsCancellationRequested)
{
Console.WriteLine("Task canceled");
break;
}
Console.WriteLine($"Task running: {i}");
Thread.Sleep(500);
}
});
Thread.Sleep(2000);
cts.Cancel();
CancellationToken
CancellationToken 是一个轻量级结构,用于传播取消请求。它由 CancellationTokenSource
生成,并可以传递给多个消费者(如异步任务或长时间运行的操作),以便它们能够监听和响应取消事件。通过这种方式,开发者可以在需要时优雅地终止这些操作,确保应用程序的高效性和响应性。
常用属性和方法
属性
IsCancellationRequested: 获取一个布尔值,指示是否已发出取消请求。此属性可以定期检查以确定是否应该停止当前操作。
方法
ThrowIfCancellationRequested(): 如果已请求取消,则抛出 OperationCanceledException
。此方法提供了一种简便的方式来立即响应取消请求,并且可以在代码的关键位置调用以确保及时处理取消信号。
Register(Action callback, bool useSynchronizationContext = true): 注册一个回调函数,在取消请求触发时执行。callback
参数是一个无参数的动作(Action),而 useSynchronizationContext
参数控制回调是否在同步上下文中执行,默认为 true
。这对于确保回调在正确的线程上执行非常重要,尤其是在 UI 应用程序中。
示例
var cts = new CancellationTokenSource();
CancellationToken token = cts.Token;
Task.Run(() => {
token.Register(() => Console.WriteLine("Cancellation registered"));
try
{
for (int i = 0; i < 10; i++)
{
token.ThrowIfCancellationRequested();
Console.WriteLine($"Task running: {i}");
Thread.Sleep(500);
}
}
catch (OperationCanceledException)
{
Console.WriteLine("Task was canceled");
}
});
Thread.Sleep(2000);
cts.Cancel();
Task与CancellationToken
Task 是.NET中的异步操作单元。结合CancellationToken
可以在任务运行时取消它。
尽早检查取消请求:在长时间运行的任务中,尽早检查 IsCancellationRequested
或调用 ThrowIfCancellationRequested()
,以便及时响应取消请求。
避免不必要的装箱操作:由于 CancellationToken
是一个结构体,尽量避免不必要的装箱操作,以保持性能。
合理设计取消逻辑:确保取消逻辑是幂等的,即多次调用取消请求不会产生副作用,并且任务能够在任何点安全地中止。
示例:取消任务
var cts = new CancellationTokenSource();
CancellationToken token = cts.Token;
Task task = Task.Run(() => {
for (int i = 0; i < 10; i++)
{
if (token.IsCancellationRequested)
{
Console.WriteLine("Task canceled");
break;
}
Console.WriteLine($"Task running: {i}");
Thread.Sleep(500);
}
}, token);
Thread.Sleep(2000);
cts.Cancel();
try
{
task.Wait();
}
catch (AggregateException ex)
{
foreach (var inner in ex.InnerExceptions)
{
if (inner is TaskCanceledException)
{
Console.WriteLine("Task cancellation exception caught");
}
}
}
示例:带超时的任务
var cts = new CancellationTokenSource(3000); // 3秒后自动取消
CancellationToken token = cts.Token;
Task.Run(() => {
try
{
for (int i = 0; i < 10; i++)
{
token.ThrowIfCancellationRequested();
Console.WriteLine($"Task running: {i}");
Thread.Sleep(1000);
}
}
catch (OperationCanceledException)
{
Console.WriteLine("Task canceled due to timeout");
}
});
总结
1、使用CancellationTokenSource
来控制取消。
2、通过CancellationToken
将取消信号传递给任务或方法。
3、任务中可以通过ThrowIfCancellationRequested
或检查IsCancellationRequested
响应取消请求。
4、合理使用Register
可以处理取消时的回调逻辑。
通过灵活运用这些工具,你可以编写更高效、可控的异步程序。
本文探讨了 Task
和 CancellationToken
的技术细节,还分享了许多实用的优化技巧。希望这些内容能够帮助大家更好地理解和应用这两个强大的工具,在未来的项目中实现更加高效和可靠的异步编程。
最后
如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。
也可以加入微信公众号 [DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!
优秀是一种习惯,欢迎大家留言学习!
作者:chenyishi
出处:cnblogs.com/chenyishi/p/18620273
声明:网络内容,仅供学习,尊重版权,侵权速删,歉意致谢!