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

发布时间:2026/7/21 8:38:04
C# Task 进阶:WaitAll / WaitAny / WhenAll / WhenAny 一、Task 同步阻塞WaitAll 与 WaitAny1. 核心原理WaitAll、WaitAny 属于同步阻塞方法执行后会阻塞当前主线程等待任务集合满足条件后才继续执行后续代码。Task.WaitAll()阻塞线程等待集合中所有任务全部执行完毕才放行后续代码Task.WaitAny()阻塞线程只要集合中任意一个任务执行完毕立刻放行后续代码案例中设置无限循环任务用于直观测试单个任务完成触发 WaitAny、永久无法全部完成触发 WaitAll 阻塞。2. 独立完整代码private void button1_Click(object sender, EventArgs e) { TaskFactory factory new TaskFactory(); ListTask taskList new ListTask(); // 添加三个异步任务第三个任务无限循环永不结束 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 与 WhenAny1. 核心原理WhenAll、WhenAny 属于异步非阻塞方法不会阻塞主线程主线程代码会直接向下执行。需搭配ContinueWith实现任务完成后的回调逻辑。Task.WhenAll()所有任务执行完毕后触发回调方法Task.WhenAny()任意一个任务执行完毕后立刻触发回调方法功能和 WaitAll/WaitAny 一致核心区别为异步不阻塞UI是项目开发主流用法。2. 独立完整代码private void button2_Click(object sender, EventArgs e) { TaskFactory factory new TaskFactory(); ListTask taskList new ListTask(); 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 / ContinueWhenAny1. 核心原理ContinueWhenAll、ContinueWhenAny是任务工厂专属方法属于语法糖等价于 WhenAll/WhenAny ContinueWith 的组合写法代码更简洁。ContinueWhenAll所有任务完成后自动执行回调ContinueWhenAny任意一个任务完成后自动执行回调2. 独立完整代码private void button3_Click(object sender, EventArgs e) { TaskFactory factory new TaskFactory(); ListTask taskList new ListTask(); 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线程可用于控制任务最大执行时长防止任务无限阻塞程序超时后任务不会终止仍在后台继续执行只是主线程不再等待五、核心知识点终极对比总结同步阻塞卡死UIWaitAll、WaitAny、Task.Wait(毫秒)适合控制台、后台同步逻辑异步非阻塞推荐WhenAll、WhenAny ContinueWith适合WinForm界面开发工厂简写ContinueWhenAll/ContinueWhenAny简化异步回调代码核心区别Wait系列阻塞主线程When系列不阻塞仅通过回调处理任务结果六、Task 同步/异步等待方法终极对比表汇总所有等待方法的核心差异清晰区分阻塞特性、用法、场景为考试和开发高频考点。方法分组具体方法阻塞核心功能配套写法适用场景核心特点同步阻塞WaitAll是等待全部任务完成放行直接调用控制台同步批量任务顺序可控卡死UI死循环会永久阻塞WaitAny是等待任意一个任务完成放行直接调用多任务快速响应响应快阻塞UI忽略剩余任务Wait(毫秒)是单个任务限时等待、超时放行绑定单个Task限制任务最大时长可超时管控超时任务后台继续运行异步非阻塞WhenAll否全部任务完成触发回调搭配ContinueWithWinForm批量异步收尾UI流畅需回调处理结果WhenAny否任意任务完成触发回调搭配ContinueWith多任务异步择优回调高效不阻塞需手动处理未完成任务ContinueWhen 系列否封装When回调一键执行TaskFactory专属工厂任务简洁开发代码极简仅适配工厂创建任务表格核心总结必背考点阻塞核心Wait 系列全为同步阻塞卡死UIWhen 系列全为异步非阻塞界面流畅功能等价WaitAll ↔ WhenAll、WaitAny ↔ WhenAny仅阻塞特性不同开发首选窗体程序优先使用 When 系列控制台可使用 Wait 系列语法糖ContinueWhen 系列是 WhenContinueWith 的简化写法专为任务工厂设计