C#测试并行任务却串行执行,问题根源是什么?
异步并行任务执行异常问题解析
问题描述
我查阅了大量关于并行任务运行的问答,编写了一段简单测试代码以验证对异步并行基础原理的理解。代码如下:
public async Task sleeper(int s) { Thread.Sleep(s); } public async Task t1() { for (int i=0; i<10; i++) { Console.WriteLine("T1: " + i); await sleeper(5000); } } public async Task t2() { for (int i=0; i<10; i++) { Console.WriteLine("T2: " + i); await sleeper(3000); } } public async Task runIt() { var task1 = t1(); var task2 = t2(); await Task.WhenAll(task1, task2); Console.WriteLine("got it"); }
预期输出为交替执行的结果,例如:
T1: 0
T2: 0
T1: 1
T1: 2
T2: 1
...
但实际得到的却是串行执行的结果:
T1: 0
T1: 1
...
T1: 9
T2: 0
T2: 1
...
想请教问题出在哪里?
问题原因与解决方法
核心问题出在sleeper方法中的Thread.Sleep(s)——这是阻塞当前线程的同步操作,并非真正的异步等待。
执行流程细节:
- 调用
t1()时,代码同步执行到await sleeper(5000),进入sleeper方法后,Thread.Sleep(5000)直接卡住当前线程,5秒内线程无法处理任何其他任务。 - 5秒后
sleeper返回,t1继续下一次循环迭代,再次阻塞线程。 - 直到
t1的10次循环全部执行完毕,线程才会开始处理t2()的代码,最终呈现串行执行的结果。
要实现预期的异步并行效果,只需将阻塞的同步等待替换为异步等待:
把Thread.Sleep(s)改为await Task.Delay(s),Task.Delay是真正的异步延迟操作,不会阻塞线程,线程可以在等待期间去执行其他任务(比如t2的代码)。
修改后的sleeper方法:
public async Task sleeper(int s) { await Task.Delay(s); }
修改后,当t1执行到await sleeper(5000)时会释放当前线程,线程可立即执行t2的代码,从而实现交替输出的并行效果。
内容的提问来源于stack exchange,提问作者Hiroto Matsuokah
相关产品推荐
相关产品推荐

