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

C# Task 进阶:WaitAll / WaitAny / WhenAll / WhenAny

一、Task 同步阻塞:WaitAll 与 WaitAny

1. 核心原理

WaitAll、WaitAny 属于同步阻塞方法,执行后会阻塞当前主线程,等待任务集合满足条件后,才继续执行后续代码。

  • Task.WaitAll():阻塞线程,等待集合中所有任务全部执行完毕,才放行后续代码

  • Task.WaitAny():阻塞线程,只要集合中任意一个任务执行完毕,立刻放行后续代码

案例中设置无限循环任务,用于直观测试:单个任务完成触发 WaitAny、永久无法全部完成触发 WaitAll 阻塞。

2. 独立完整代码

private void button1_Click(object sender, EventArgs e) { TaskFactory factory = new TaskFactory(); List<Task> taskList = new List<Task>(); // 添加三个异步任务,第三个任务无限循环永不结束 taskList.Add(factory.StartNew(() => { Console.WriteLine("查询数据库"); })); taskList.Add(factory.StartNew(() => { Console.WriteLine("查询缓存"); })); taskList.Add(factory.StartNew(() => { while (true) { } Console.WriteLine("查询接口"); })); // 同步阻塞:任意一个任务完成即放行 Task.WaitAny(taskList.ToArray()); // 所有任务满足条件后执行 Console.WriteLine("至少一个操作执行完毕,主线程放行"); }

3. 注意事项

  • WaitAll、WaitAny 为同步方法,会直接阻塞UI主线程,造成窗体卡死,WinForm 项目慎用

  • 存在永久执行的任务时,WaitAll 会永久死锁阻塞,永远无法放行

  • WaitAny 只判断首个完成的任务,不关心剩余任务执行状态

  • 适用于控制台程序同步等待,不推荐窗体UI线程直接调用


二、Task 异步回调:WhenAll 与 WhenAny

1. 核心原理

WhenAll、WhenAny 属于异步非阻塞方法,不会阻塞主线程,主线程代码会直接向下执行。需搭配ContinueWith实现任务完成后的回调逻辑。

  • Task.WhenAll():所有任务执行完毕后,触发回调方法

  • Task.WhenAny():任意一个任务执行完毕后,立刻触发回调方法

功能和 WaitAll/WaitAny 一致,核心区别为异步不阻塞UI,是项目开发主流用法。

2. 独立完整代码

private void button2_Click(object sender, EventArgs e) { TaskFactory factory = new TaskFactory(); List<Task> taskList = new List<Task>(); taskList.Add(factory.StartNew(() => { Console.WriteLine("查询数据库"); })); taskList.Add(factory.StartNew(() => { Console.WriteLine("查询缓存"); })); taskList.Add(factory.StartNew(() => { while (true) { } Console.WriteLine("查询接口"); })); // 异步非阻塞:任意任务完成后触发回调 Task.WhenAny(taskList.ToArray()).ContinueWith(t => { Console.WriteLine("至少一个异步操作执行完了"); }); // 主线程不阻塞,直接执行 Console.WriteLine("主线程继续执行,不卡顿"); }

3. 注意事项

  • When 系列方法异步无阻塞,完美解决UI卡死问题,优先用于WinForm/WPF项目

  • 必须搭配 ContinueWith 使用,否则无法捕获任务完成事件

  • 主线程代码执行顺序优先于回调代码

  • 存在死循环任务时,WhenAll 回调永远不会触发


三、TaskFactory 自带回调:ContinueWhenAll / ContinueWhenAny

1. 核心原理

ContinueWhenAllContinueWhenAny是任务工厂专属方法,属于语法糖,等价于 WhenAll/WhenAny + ContinueWith 的组合写法,代码更简洁。

  • ContinueWhenAll:所有任务完成后自动执行回调

  • ContinueWhenAny:任意一个任务完成后自动执行回调

2. 独立完整代码

private void button3_Click(object sender, EventArgs e) { TaskFactory factory = new TaskFactory(); List<Task> taskList = new List<Task>(); taskList.Add(factory.StartNew(() => { Console.WriteLine("查询数据库"); })); taskList.Add(factory.StartNew(() => { Console.WriteLine("查询缓存"); })); taskList.Add(factory.StartNew(() => { while (true) { } Console.WriteLine("查询接口"); })); // 工厂自带回调:任意任务完成触发 factory.ContinueWhenAny(taskList.ToArray(), (t) => { Console.WriteLine("至少一个操作执行完了"); }); }

3. 注意事项

  • 无需手动写 WhenAny/WhenAll 和 ContinueWith,封装度更高

  • 仅 TaskFactory 创建的任务集合推荐使用该写法

  • 本质仍是异步回调,不会阻塞主线程


四、Task 单个任务限时等待 Wait(int 毫秒)

1. 核心原理

单个 Task 自带Wait(毫秒)重载方法,作用是限时同步阻塞等待任务执行。等待时间内任务完成则直接放行,超时则主动结束等待,继续执行后续代码。

2. 独立完整代码

private void button4_Click(object sender, EventArgs e) { Task t1 = new Task(() => { Console.WriteLine("任务执行中"); Thread.Sleep(2000); // 任务耗时2秒 }); t1.Start(); // 限时等待1秒,超时自动放行 t1.Wait(1000); Console.WriteLine("等待结束,执行后续代码"); }

3. 注意事项

  • 属于同步阻塞方法,限时期间会卡住UI线程

  • 可用于控制任务最大执行时长,防止任务无限阻塞程序

  • 超时后任务不会终止,仍在后台继续执行,只是主线程不再等待


五、核心知识点终极对比总结

  • 同步阻塞(卡死UI):WaitAll、WaitAny、Task.Wait(毫秒),适合控制台、后台同步逻辑

  • 异步非阻塞(推荐):WhenAll、WhenAny + ContinueWith,适合WinForm界面开发

  • 工厂简写:ContinueWhenAll/ContinueWhenAny,简化异步回调代码

  • 核心区别:Wait系列阻塞主线程,When系列不阻塞,仅通过回调处理任务结果


六、Task 同步/异步等待方法终极对比表

汇总所有等待方法的核心差异,清晰区分阻塞特性、用法、场景,为考试和开发高频考点。

方法分组

具体方法

阻塞

核心功能

配套写法

适用场景

核心特点

同步阻塞

WaitAll

等待全部任务完成放行

直接调用

控制台同步批量任务

顺序可控,卡死UI;死循环会永久阻塞

WaitAny

等待任意一个任务完成放行

直接调用

多任务快速响应

响应快,阻塞UI,忽略剩余任务

Wait(毫秒)

单个任务限时等待、超时放行

绑定单个Task

限制任务最大时长

可超时管控,超时任务后台继续运行

异步非阻塞

WhenAll

全部任务完成触发回调

搭配ContinueWith

WinForm批量异步收尾

UI流畅,需回调处理结果

WhenAny

任意任务完成触发回调

搭配ContinueWith

多任务异步择优回调

高效不阻塞,需手动处理未完成任务

ContinueWhen 系列

封装When+回调,一键执行

TaskFactory专属

工厂任务简洁开发

代码极简,仅适配工厂创建任务

表格核心总结(必背考点)

  • 阻塞核心:Wait 系列全为同步阻塞,卡死UI;When 系列全为异步非阻塞,界面流畅

  • 功能等价:WaitAll ↔ WhenAll、WaitAny ↔ WhenAny,仅阻塞特性不同

  • 开发首选:窗体程序优先使用 When 系列,控制台可使用 Wait 系列

  • 语法糖:ContinueWhen 系列是 When+ContinueWith 的简化写法,专为任务工厂设计

http://www.jsqmd.com/news/1233529/

相关文章:

  • 苹果AI战略转型:Gemini技术集成与Siri重构
  • AI培训项目风险管理与成本控制实践
  • Python高效开发:2020年十大实用库解析与应用
  • 3步完成GitHub汉化:终极GitHub中文插件安装指南
  • 具身智能的TVA-VLA双引擎架构(2)
  • Unity集成BepuPhysics2:突破物理性能瓶颈的架构设计与工程实践
  • 数据科学实习通关路径:JD反向拆解与鲁棒性工程实践
  • 2026精选:本土制造企业实力与创新产品深度解析 - 甄选服务推荐
  • AI时代Java程序员的核心竞争力:从CRUD到架构师的价值跃迁
  • 如何快速优化游戏性能:终极时间控制指南
  • 基于Spring Boot+Vue的毕业设计:员工绩效考核系统实战指南
  • 从“统一位宽是浪费”说起:一种自适应混合基数分解的LLM权重压缩构想
  • 最近试了下AI Offer,用AI来进化简历和模拟面试还挺简单的
  • 具身智能的TVA-VLA双引擎架构(3)
  • Python自动化报表生成教程
  • SCMP证书报考官网怎么找 - 众智商学院官方
  • 名校招生机制解析:公平性与多元化的平衡之道
  • LangChain与LangGraph框架选型指南:智能体开发实战解析
  • 徐州 24 小时上门回收黄金深度实测科普|2026 七月大盘行情,居家变现全套风险排查与正规门店服务标准 - 不晚生活号
  • AI代码生成与艺术风格融合:Codex转生成摇曳鳗一舞部署实践
  • 教材看不懂、难题没人教、答案看不懂——暑期学习三大难题,百分书童一个APP全解决
  • Windows系统文件dswave.dll丢失找不到问题解决
  • 深入解析TI C2000 ePWM高级功能:斩波、故障保护与数字比较实战指南
  • HarmonyOS7基础吸附滚动页实战:ScrollSnap 基础吸附行为与滚动停靠
  • 具身智能的TVA-VLA双引擎架构(5)
  • UE5覆层材质无效?深度解析渲染原理与系统性解决方案
  • 开源项目维护停滞的应对策略与风险评估指南
  • YARP网关统一管理CORS跨域配置实战
  • FileList了解到制作--日志3
  • LangChain框架:构建大语言模型应用的模块化解决方案