我以两种不同的方式运行Parallel.For循环:
不写任何async / await,只是调用Task ReadSensorAsync(int)
:
var watch = System.Diagnostics.Stopwatch.StartNew();
Parallel.For(3, 38,
index => {
ReadSensorsAsync(index);
});
watch.Stop();
Console.WriteLine("Parallel finished in {0} ms", watch.ElapsedMilliseconds);
时间显示1ms
使用async/await
var watch = System.Diagnostics.Stopwatch.StartNew();
Parallel.For(3, 38,
async index => {
await ReadSensorsAsync(index);
});
watch.Stop();
Console.WriteLine("Parallel finished in {0} ms", watch.ElapsedMilliseconds);
显示2-5ms
。
问题是为什么存在这样的差异以及使用哪种方式。
答案 0 :(得分:5)
首先,这两个版本都没有任何意义。 Parallel.For
用于运行CPU绑定(或可能阻止IO绑定)操作。您正在使用它来启动异步操作。
你不是在等待操作完成,你说这是故意的,但它也很危险:如果在ReadSensorsAsync
中发生异常,你就无法捕捉它。
由于启动异步操作应该非常快,要一次启动多个操作,您不需要Parallel.For
,您可以使用普通for
:
for (int i = 3; i < 38; i++)
{
ReadSensorsAsync(i);
}
(但同样,我不建议忽略返回的Task
。)
至于计时,最大的区别可能是因为你忽略了热身:当你第一次调用ReadSensorsAsync
时,必须进行JIT编译,对于这种简单的操作,这会显着地扭曲结果
以下是我机器上的数字,格式是“第一次运行”; “第二次跑”:
ReadSensorsAsync
一次(用于比较):7.6 ms; 0.04毫秒for
:7.5毫秒; 0.05毫秒Parallel.For
没有await
:8.0毫秒; 0.5毫秒Parallel.For
await
:11毫秒; 2.6毫秒如您所见,使用Parallel.For
只会增加开销。将它与await
一起使用会增加更多开销,因为启动async
方法需要创建状态机,这需要一些时间。