C# 异步编程技巧 Task 和 CancellationTokenSource 的妙用

前言

在程序开发中异步编程和任务管理是确保高效、响应式用户体验的关键。C# 提供强大的工具来处理这些需求,其中 Task 和 CancellationTokenSource 是两个非常重要的组件。Task 用于管理和协调异步操作,而 CancellationTokenSource 则提供优雅的方式来取消或中断这些操作。

在.NET中,CancellationTokenSourceCancellationTokenTask是处理异步操作和取消任务的重要工具。本文将通过一些简单的例子,帮助大家理解它们的用法和协作方式。

正文

CancellationTokenSource

CancellationTokenSource是 C# 中用于生成和管理 CancellationToken 的类,它充当取消操作的触发器。

通过 CancellationTokenSource,开发者可以控制取消信号的发出,并将这些信号传递给多个异步任务或长时间运行的操作,以便它们能够响应取消请求并优雅地终止。

常用属性和方法
属性

Token: 返回与此源关联的 CancellationToken。每个 CancellationTokenSource 实例都可以生成一个唯一的 CancellationToken,该令牌可以传递给多个消费者以监听取消事件。

方法

Cancel(): 触发取消操作。调用此方法后,所有与该 CancellationTokenSource 关联的 CancellationToken 将进入已取消状态,通知所有监听者执行取消逻辑。

CancelAfter(int millisecondsDelay): 设置一个计时器,在指定的毫秒数后自动触发取消操作。这对于设置超时非常有用,确保长时间运行的任务不会无限期挂起。

Dispose(): 释放由 CancellationTokenSource 占用的资源。调用此方法后,不能再使用该实例触发取消操作。建议在不再需要 CancellationTokenSource 时调用 Dispose(),以避免资源泄漏。

示例
 

csharp

代码解读

复制代码

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 应用程序中。

示例
 

csharp

代码解读

复制代码

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 是一个结构体,尽量避免不必要的装箱操作,以保持性能。

合理设计取消逻辑:确保取消逻辑是幂等的,即多次调用取消请求不会产生副作用,并且任务能够在任何点安全地中止。

示例:取消任务
 

csharp

代码解读

复制代码

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"); } } }

示例:带超时的任务
 

csharp

代码解读

复制代码

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 的技术细节,还分享了许多实用的优化技巧。希望这些内容能够帮助大家更好地理解和应用这两个强大的工具,在未来的项目中实现更加高效和可靠的异步编程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值