编辑
2025-09-24
C#
00

目录

摘要
正文

摘要


在 C# 中,CancellationTokenSource 是一个用于创建和管理 CancellationToken(取消标记)的类。它提供了一种简单的方式来请求取消异步或多线程操作。

正文


看一下Cancel的顺序

C#
static void Main(string[] args) { CancellationTokenSource cts = new CancellationTokenSource(); CancellationToken cancellationToken = cts.Token; cancellationToken.Register(() => { Console.WriteLine("Cancel1..."); }); cancellationToken.Register(() => { Console.WriteLine("Cancel2..."); }); cancellationToken.Register(state => { Console.WriteLine("Cancel3..." + state.ToString()); }, "OK"); Console.WriteLine("开始..."); cts.Cancel(); }

image.png

取消异步操作:在进行异步操作时,可能需要提供取消操作的能力,以便在需要时中止操作。使用 CancellationTokenSource 创建 CancellationToken,并将其传递给异步方法,然后在需要取消操作时,调用 CancellationTokenSource 的 Cancel() 方法。

C#
static async Task Main(string[] args) { CancellationTokenSource cts = new CancellationTokenSource(); CancellationToken cancellationToken = cts.Token; //启动任务 Task asyncOperationTask = DoAsyncOption(cancellationToken); await Task.Delay(2000); cts.Cancel(); } async static Task DoAsyncOption(CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { Console.WriteLine("do..."); await Task.Delay(500, cancellationToken); } }

image.png

取消多线程操作:在多线程环境中,有时需要在另一个线程中通知某个线程进行取消。CancellationTokenSource 可以用来创建 CancellationToken,并将其传递给需要取消的线程。

C#
static CancellationTokenSource cts = new CancellationTokenSource(); static CancellationToken cancellationToken; static async Task Main(string[] args) { cancellationToken = cts.Token; //启动任务 Task asyncOperationTask = DoAsyncOption(); //开启管理任务 await Do(); while (true) { } } async static Task Do() { int x = 0; while (true) { x++; if (x == 10) { cts.Cancel(); } await Task.Delay(500); } } async static Task DoAsyncOption() { while (!cancellationToken.IsCancellationRequested) { Console.WriteLine("do..."); await Task.Delay(500); } }

超时处理:在执行某些操作时,可以设置一个超时,如果操作在指定时间内未完成,就取消它。

C#
static async Task Main(string[] args) { CancellationTokenSource cts = new CancellationTokenSource(5000);//设置超时 CancellationToken cancellationToken = cts.Token; Task task = DoOperationWithTimeout(cts.Token); while (true) { } } async static Task DoOperationWithTimeout(CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { Console.WriteLine("do..."); await Task.Delay(500); } }

image.png

取消链:CancellationTokenSource 提供了 CreateLinkedTokenSource 方法,可以将多个 CancellationToken 组合成一个联动的取消标记。只要其中一个标记被取消,链中的所有标记都会收到取消请求。

C#
static async Task Main(string[] args) { CancellationTokenSource cts = new CancellationTokenSource(5000);//设置超时 CancellationToken cancellationToken = cts.Token; DoOperationWithLinkedToken(cancellationToken); await Task.Delay(5000); cts.Cancel(); while (true) { } } static async void DoOperationWithLinkedToken(CancellationToken cancellationToken) { //任意一个cancel都会cancel using (var cts1 = new CancellationTokenSource()) using (var cts2 = new CancellationTokenSource()) { using (var combinedCts = CancellationTokenSource.CreateLinkedTokenSource(cts1.Token, cts2.Token, cancellationToken)) { while (!combinedCts.IsCancellationRequested) { Console.WriteLine("do..."); await Task.Delay(500); } } } }

image.png

监视取消请求:可以通过 CancellationTokenSource 的 Token 属性来监视取消请求,并在取消时执行相应的操作。

C#
static async Task Main(string[] args) { CancellationTokenSource cts = new CancellationTokenSource(5000);//设置超时 CancellationToken cancellationToken = cts.Token; MonitorCancellation(cancellationToken); for (int i = 0; i < 10; i++) { if (cancellationToken.IsCancellationRequested) { break; } Console.WriteLine("do..."); await Task.Delay(1000); } cts.Cancel(); while (true) { } } static void MonitorCancellation(CancellationToken cancellationToken) { cancellationToken.Register(() => Console.WriteLine("Cancellation requested.")); }

使用 IsCancellationRequested 来判断线程比用自己自定义一个变量是否应该退出有以下好处:

  1. 与取消标记一起使用IsCancellationRequested 属性是 CancellationToken 结构的一部分。CancellationToken 是用于协调线程和任务之间取消操作的一种机制。它可以在多个线程之间安全地传递,而不需要使用额外的同步机制。这种方式可以确保线程在需要退出时得到通知。
  2. 标准化取消机制: CancellationToken 是 .NET 中用于取消操作的标准化机制。它是线程安全的,并且在异步编程中有广泛的应用。使用 IsCancellationRequested 与 CancellationToken 结合使用,可以确保代码在取消时行为一致且安全。
  3. 减少状态管理复杂性:通过使用 CancellationToken 和 IsCancellationRequested,可以将取消状态与需要取消的操作绑定在一起,而不是单独维护一个变量来表示取消状态。这样可以减少状态管理的复杂性,提高代码的可读性和可维护性。
  4. 避免竞态条件:使用自己定义的变量来管理线程退出可能导致竞态条件(Race Condition)。竞态条件是指多个线程对共享资源的访问顺序不确定,可能导致出现不稳定或错误的结果。而 CancellationToken 提供了一种线程安全的机制,能够更好地避免这类问题。

在 .NET 中,如果你需要在多线程环境下管理任务的取消,推荐使用 CancellationToken 和 IsCancellationRequested 属性。这些属性可以确保任务能够及时响应取消请求,避免出现意外的运行时错误。当然,如果你的场景比较特殊,或者需要实现一些非标准化的取消机制,也可以使用自定义的取消机制,但需要注意这种方式可能会增加代码的复杂性和难度。

本文作者:技术老小子

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!