使用Thread.Sleep的并行任务未按预期并发执行的原因是什么?
问题根源
你的Method1和Method2本质是同步方法,虽然返回值是Task类型,但没有任何异步执行的逻辑,所有代码都会在调用线程直接串行执行:
- 执行
var task1 = Method1(sw);时,当前线程会直接运行Method1内的全部代码,包括阻塞3秒的Thread.Sleep(3000),打印完结果后返回已经执行完成的Task,才会继续往下走 - 执行
var task2 = Method2(sw);时,又会在当前线程阻塞3秒,跑完Method2全部逻辑才返回已完成的Task - 后续不管是分开
await两个Task,还是用Task.WhenAll,等待的都是已经执行完成的Task,不会改变串行执行的结果,所以总耗时是6秒。
Task.FromResult仅用于包装已经计算完成的结果返回,不会启动新的任务执行逻辑,因此也不会产生异步效果。
修复方案
方案1:改为真正的异步方法
如果方法内部可以使用异步逻辑,用async修饰方法,将同步阻塞的Thread.Sleep替换为异步等待的Task.Delay:
static async Task<bool> Method1(Stopwatch sw) { await Task.Delay(3000); Console.WriteLine("Method1 " + sw.ElapsedMilliseconds); return true; } static async Task<bool> Method2(Stopwatch sw) { await Task.Delay(3000); Console.WriteLine("Method2 " + sw.ElapsedMilliseconds); return false; }
修改后调用方法时,遇到await Task.Delay会立即返回未完成的Task,两个方法的等待逻辑会并行执行,总耗时约3秒,符合你的预期。
方案2:将同步方法丢到线程池并行执行
如果方法内部必须保留同步逻辑,可以在调用时用Task.Run把方法包裹,丢到线程池线程并行执行:
var task1 = Task.Run(() => Method1(sw)); var task2 = Task.Run(() => Method2(sw));
这种方式下两个同步方法会在线程池独立线程运行,也能实现并行效果,总耗时约3秒。
内容的提问来源于stack exchange,提问作者aknag
相关产品推荐
相关产品推荐

