线程任务取消——CancellationToken
在多线程环境下,CancellationToken 是 .NET 中用于协作式取消操作的标准机制。
CancellationTokenSource:这是“发布者”。它负责在需要取消时发出信号(调用 .Cancel())。
CancellationToken:这是“订阅者”或“载体”。它是一个轻量级的结构体,被传递给各个任务或线程。
在多线程/Task中,token主要有三种使用方式:
1、注册回调
注册一个委托,当取消被请求时,该委托会被执行。
常用于释放非托管资源或中断阻塞操作
CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource(); CancellationToken token = _cancellationTokenSource.Token; // 注册一个回调,当取消发生时执行 token.Register(() => { Console.WriteLine("取消请求已收到,正在清理资源..."); // 在这里执行清理逻辑,例如关闭流、释放句柄等 });
2、轮询检查(IsCancellationRequested)
常用于长时间运行的循环中
Task.Run(() => { for (int i = 0; i < 1000; i++) { // 1. 检查是否请求了取消 if (token.IsCancellationRequested) { Console.WriteLine("任务被取消,正在退出循环。"); // 2. 优雅地退出,或者抛出异常 token.ThrowIfCancellationRequested(); } // 模拟工作 Console.WriteLine($"处理中: {i}"); Thread.Sleep(100); } }, token); // 注意:将 token 传递给 Task.Run 本身也有助于在取消时阻止任务开始
3、传递给异步API
许多 .NET 异步方法(如 Stream.ReadAsync, HttpClient.GetAsync)都接受 CancellationToken 作为参数。这允许这些底层操作在收到取消信号时立即停止 I/O 操作,而不是等待完成。
// 假设这是一个耗时的网络请求 try { // 将 token 传递给异步方法 var result = await httpClient.GetAsync("https://example.com", token); } catch (OperationCanceledException) { Console.WriteLine("网络请求已被取消。"); }
4、使用Demo
using System;
using System.Threading;
using System.Threading.Tasks; namespace CancellationTokenDemo { // 这里是你提供的 Worker 类定义 public class Worker { private CancellationTokenSource _cancellationTokenSource; public void StartWork() { _cancellationTokenSource = new CancellationTokenSource(); CancellationToken token = _cancellationTokenSource.Token; Task.Run(() => { try { Console.WriteLine("🚀 任务开始运行..."); for (int i = 0; i < 10; i++) { // 关键点:在循环中检查是否请求了取消 token.ThrowIfCancellationRequested(); Console.WriteLine($"⏳ 正在处理... {i * 10}%"); // 模拟耗时操作 (这里使用 Thread.Sleep 模拟阻塞) // 在实际异步代码中,通常使用 Task.Delay(..., token) Thread.Sleep(500); } Console.WriteLine("✅ 工作正常完成。"); } catch (OperationCanceledException) { // 捕获取消异常,进行清理或记录日志 Console.WriteLine("🛑 捕获到取消请求,任务已停止。"); } }, token); } public void StopWork() { // 触发取消信号 // 注意:这里不需要 Dispose,通常由拥有者管理生命周期 if (_cancellationTokenSource != null && !_cancellationTokenSource.IsCancellationRequested) { Console.WriteLine("\n📤 正在调用 StopWork 发送取消信号..."); _cancellationTokenSource.Cancel(); } } // 建议实现 IDisposable 模式或在程序退出时调用 public void Cleanup() { _cancellationTokenSource?.Dispose(); Console.WriteLine("🧹 资源已释放。"); } } class Program { static void Main(string[] args) { Console.WriteLine("=== C# CancellationToken 演示 ==="); // 1. 实例化 Worker Worker worker = new Worker(); // 2. 启动后台任务 worker.StartWork(); // 3. 模拟主线程等待用户输入 // 在实际场景中,这里可能是服务器监听、UI 事件循环等 Console.WriteLine("按任意键取消任务,或等待任务自动完成..."); Console.ReadKey(); // 4. 触发取消 worker.StopWork(); // 5. 给一点时间让后台任务处理取消信号并退出 // (在实际生产代码中,通常会 await Task.WhenAny(...) 或 .Wait()) Thread.Sleep(1000); // 6. 清理资源 worker.Cleanup(); Console.WriteLine("程序结束。按任意键退出。"); Console.ReadKey(); } } }
------------------------------------
承接
**视觉检测软件开发及调试
**工业软件开发
**上位机软件开发
wechat:luoran2024
qq:565934058
email:taoyuansu@qq.com
海量教育资源及影视资源下载
微信公众号:EFun科技
------------------------------------

浙公网安备 33010602011771号