当前位置: 首页 > news >正文

CancellationToken与Abort

文章目录

  • 1、什么是 CancellationToken
  • 2、 核心作用:三大功能
    • 2.1 协作式取消 - "礼貌的请求"
    • 2.2 资源安全 - "优雅的退场"
    • 2.3 传播机制 - "连锁反应"
  • 3、底层原理
    • 3.1 简单而高效的设计
    • 3.2 工作流程
  • 4、CancellationToken vs Thread.Abort:文明 vs 暴力
    • 4.1 CancellationToken(文明的红绿灯)
    • 4.2 Thread.Abort(暴力的拖车)
    • 4.3 📊 详细对比表格
  • 5、实际应用场景
    • 5.1 场景1:用户界面响应
    • 5.2 场景2:超时控制
    • 5.3 场景3:多个取消条件
  • 6、最佳实践
    • 6.1 ✅ 正确做法
    • 6.2 ❌ 错误做法
  • 7、总结

1、什么是 CancellationToken

什么是 CancellationToken?—— “文明的红绿灯系统”

想象一下交通系统:

  • CancellationTokenSource = 交通指挥中心

  • CancellationToken = 司机看到的红绿灯

  • ThrowIfCancellationRequested() = 司机抬头看灯的动作

// 建立交通系统
var 指挥中心 = new CancellationTokenSource();
var 红绿灯 = 指挥中心.Token;// 司机开始行驶
var 送货任务 = Task.Run(() =>
{for (int 路口 = 0; 路口 < 100; 路口++){// 🚦 司机主动看红绿灯红绿灯.ThrowIfCancellationRequested();// 安全行驶到下一个路口开车到路口(路口);}
});// 指挥中心把绿灯变红灯
指挥中心.Cancel();

2、 核心作用:三大功能

2.1 协作式取消 - “礼貌的请求”

// 不是强制停止,而是礼貌地请求停止
var cts = new CancellationTokenSource();var worker = Task.Run(() =>
{while (!cts.Token.IsCancellationRequested) // 主动检查{// 工作...Console.WriteLine("工作中...");Thread.Sleep(1000);// 在合适的地方安全停止if (cts.Token.IsCancellationRequested){Console.WriteLine("收到停止请求,正在安全收尾...");// 清理资源、保存状态...break;}}
});// 3秒后礼貌地请求停止
await Task.Delay(3000);
cts.Cancel(); // 只是发出请求,不强制停止

2.2 资源安全 - “优雅的退场”

public async Task ProcessFileAsync(string filePath, CancellationToken ct)
{// 获取资源using var fileStream = File.OpenRead(filePath);using var reader = new StreamReader(fileStream);try{while (!reader.EndOfStream){ct.ThrowIfCancellationRequested(); // 检查点var line = await reader.ReadLineAsync();await ProcessLineAsync(line, ct); // 传递取消令牌ct.ThrowIfCancellationRequested(); // 再次检查}}catch (OperationCanceledException){// 🛑 安全清理:using语句会自动释放资源Console.WriteLine("取消时已自动释放文件资源");throw;}
}

2.3 传播机制 - “连锁反应”

// 一个取消信号,多个任务响应
var mainCts = new CancellationTokenSource();// 任务1:文件处理
var fileTask = ProcessFilesAsync(mainCts.Token);// 任务2:网络请求  
var networkTask = FetchDataAsync(mainCts.Token);// 任务3:数据计算
var computeTask = CalculateAsync(mainCts.Token);// 一个取消信号,所有任务都会收到
await Task.Delay(2000);
mainCts.Cancel(); // 所有任务都会优雅停止try
{await Task.WhenAll(fileTask, networkTask, computeTask);
}
catch (OperationCanceledException)
{Console.WriteLine("所有任务已安全取消");
}

3、底层原理

3.1 简单而高效的设计

// 简化的底层结构
public class CancellationTokenSource
{private volatile bool _isCancellationRequested; // 🎯 核心:一个布尔标志private List<Action> _callbacks = new List<Action>(); // 回调列表public CancellationToken Token => new CancellationToken(this);public void Cancel(){_isCancellationRequested = true; // 1. 设置标志位foreach (var callback in _callbacks) // 2. 执行回调callback.Invoke();}
}public struct CancellationToken
{private CancellationTokenSource _source;public bool IsCancellationRequested => _source?._isCancellationRequested ?? false;public void ThrowIfCancellationRequested(){if (IsCancellationRequested) // 🎯 只是检查布尔值throw new OperationCanceledException();}
}

3.2 工作流程

1. 创建: CancellationTokenSource cts = new()2. 传递: 将 cts.Token 传递给任务↓  
3. 检查: 任务中调用 token.ThrowIfCancellationRequested()4. 取消: 外部调用 cts.Cancel()5. 响应: 下次检查时任务抛出 OperationCanceledException↓
6. 清理:catch块中安全释放资源

4、CancellationToken vs Thread.Abort:文明 vs 暴力

4.1 CancellationToken(文明的红绿灯)

优点

// ✅ 安全可控
var cts = new CancellationTokenSource();
try
{await LongRunningOperation(cts.Token);
}
catch (OperationCanceledException)
{// 知道操作在安全状态下停止
}// ✅ 资源安全
using (var resource = AcquireResource())
{while (!ct.IsCancellationRequested){// 工作...}// using块确保资源被释放
}// ✅ 可预测性
// 你知道取消会在哪个检查点发生

4.2 Thread.Abort(暴力的拖车)

缺点:

// ❌ 危险!
var thread = new Thread(() =>
{using (var file = File.OpenWrite("data.dat")){for (int i = 0; i < 1000000; i++){// 如果在这里被Abort,文件可能损坏!WriteData(file, i);}}
});thread.Start();
thread.Abort(); // 💥 可能破坏文件数据!// ❌ 资源泄漏
// 可能无法执行finally块和Dispose()

4.3 📊 详细对比表格

特性CancellationTokenThread.Abort
控制方式协作式 - 任务主动配合强制式 - 外部强行中断
安全性⭐⭐⭐⭐⭐ 非常安全⭐ 非常危险
资源管理✅ 确保资源清理❌ 可能泄漏资源
可预测性✅ 知道停止位置❌ 任意位置停止
数据一致性✅ 保持数据完整❌ 可能破坏数据
.NET Core✅ 完全支持❌ 已移除
使用场景现代异步编程遗留代码(避免使用)

5、实际应用场景

5.1 场景1:用户界面响应

// 用户点击"取消"按钮时停止操作
private CancellationTokenSource _searchCts;private async void SearchButton_Click(object sender, EventArgs e)
{// 取消之前的搜索_searchCts?.Cancel();_searchCts = new CancellationTokenSource();try{await SearchAsync(searchTextBox.Text, _searchCts.Token);statusLabel.Text = "搜索完成";}catch (OperationCanceledException){statusLabel.Text = "搜索已取消";}
}private void CancelButton_Click(object sender, EventArgs e)
{_searchCts?.Cancel(); // 用户点击取消
}

5.2 场景2:超时控制

// 5秒超时自动取消
public async Task<T> ExecuteWithTimeoutAsync<T>(Func<CancellationToken, Task<T>> operation)
{using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));try{return await operation(cts.Token);}catch (OperationCanceledException) when (cts.Token.IsCancellationRequested){throw new TimeoutException("操作超时");}
}// 使用
var result = await ExecuteWithTimeoutAsync(async ct =>
{await Task.Delay(10000, ct); // 模拟长时间操作return "结果";
});

5.3 场景3:多个取消条件

// 组合多个取消条件
public async Task ProcessDataAsync(CancellationToken userToken = default)
{// 超时取消:最多运行30秒using var timeoutCts = new CancellationTokenSource(TimeSpan.FromSeconds(30));// 用户取消 + 超时取消using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(userToken, timeoutCts.Token);await DoWorkAsync(linkedCts.Token);
}

6、最佳实践

6.1 ✅ 正确做法

// 1. 及时检查取消
public async Task LongOperationAsync(CancellationToken ct)
{for (int i = 0; i < 100; i++){ct.ThrowIfCancellationRequested(); // 频繁检查await ProcessItemAsync(i, ct);}
}// 2. 传递取消令牌
public async Task ProcessItemAsync(int id, CancellationToken ct)
{// 将取消令牌传递给所有异步操作await httpClient.GetAsync(url, ct);await fileStream.ReadAsync(buffer, 0, buffer.Length, ct);
}// 3. 合理使用using
public async Task ProcessAsync(CancellationToken ct)
{using var cts = CancellationTokenSource.CreateLinkedTokenSource(ct);cts.CancelAfter(TimeSpan.FromMinutes(5)); // 附加超时await DoWorkAsync(cts.Token);
}

6.2 ❌ 错误做法

// 1. 忽略取消令牌
public async Task BadMethodAsync(CancellationToken ct) // ❌ 参数不用
{// 从不检查取消,调用者无法取消这个操作await Task.Delay(10000); 
}// 2. 不及时检查
public void LongRunningCalculation(CancellationToken ct)
{for (int i = 0; i < 1000000; i++){// 每100万次迭代才检查一次!❌if (i % 1000000 == 0)ct.ThrowIfCancellationRequested();HeavyCalculation(i);}
}// 3. 不传递取消令牌
public async Task<string> DownloadAsync(CancellationToken ct)
{// ❌ 没有传递取消令牌,网络请求无法取消return await httpClient.GetStringAsync("http://example.com");
}

7、总结

CancellationToken 是现代C#异步编程的基石:

🎯 核心优势:

  • 安全第一:不会破坏数据或泄漏资源

  • 协作友好:任务可以优雅地结束工作

  • 灵活传播:一个取消信号可以传递给多个操作

  • 性能高效:底层只是简单的标志位检查

🚫 Thread.Abort 已被淘汰的原因:

  • 像"拔电源"一样危险

  • 可能在任何代码位置中断,导致状态不一致

  • .NET Core/5+ 中已不再支持

用 CancellationToken 就像用红绿灯 - 安全、可预测、文明
用 Thread.Abort 就像强行拖车 - 危险、破坏性、已过时

在现代C#开发中,始终使用 CancellationToken 来管理异步操作的取消,这是编写健壮、可靠应用程序的关键!

http://www.dtcms.com/a/466123.html

相关文章:

  • linux达梦数据库操作
  • [自荐]一款mac电脑历史剪切板工具,类似著名的Paste
  • 二级域名可以做不同的网站吗网站建设网络推广广告语
  • MapReduce简介
  • FreeType 2.7 – 卓越的 Linux 字体质量
  • 龙江建站技术wordpress 管理 主题
  • 企业网站建设 制作网站建设基本流程流程图
  • 【Homebrew安装 MySQL 】macOS 用 Homebrew 安装 MySQL 完整教程
  • 【图像处理基石】暗光增强算法入门:从原理到实战(Python+OpenCV)
  • Asp.net core Kestrel服务器详解
  • OpenFeign使用
  • 如何在鸿蒙中实现毫秒级数据检索?哈希表与二分查找的双引擎优化方案
  • 实现支持链式调用的 JavaScript 类
  • 中文wordpress模板免费seo教程分享
  • 如何用ps做网站顺德网站建设7starry
  • 京东agent之joyagent解读
  • 【第五章:计算机视觉-项目实战之生成式算法实战:扩散模型】3.生成式算法实战:扩散模型-(2)DDPM数据读取
  • UCC21530-Q1 隔离栅极驱动器完全解析:从原理到实战应用
  • 企业网站的网络营销功能wordpress 发视频
  • 创作纪念日
  • 直接找高校研究生做网站行吗公众号开发单位
  • 怎么看网站开发语言是哪种律所网站建设建议
  • Docker:公有仓库和私有仓库的搭建
  • 有专门做牙膏的网站吗网站footer设计
  • 零基础从头教学Linux(Day 47)
  • libevent输出缓存区的数据
  • 宋红康 JVM 笔记 Day18|class文件结构
  • 网站源代码购买荆州 网站建设
  • ws2_32.dll文件丢失或损坏怎么办?4种有效修复方案分享
  • Rust程序语言设计(5-8)