编辑:
我看到您的实际问题有点误导,我会尝试回答故意的问题。具体来说,使用AsParallel 将是一个好方法,因为您实际上不需要await。由于您正在处理集合,因此 PLINQ 或 Paralle.ForEach 是一个不错的选择。当您有自然的异步 I/O 绑定操作时,请考虑使用 async-await。建议不要wrap synchronous methods with async wrappers.
如果您实际测试您的代码,您甚至可能会惊讶地发现并行这段代码实际上会对您的方法执行产生负性能成本,具体取决于大小 em> 您正在迭代的数组。
很多时候人们忘记了使用线程实际上是有开销的,即使使用线程池之外的线程也是如此。您必须进行最少的 CPU 密集型工作,才能让并行化的性能受到影响。
如果你的数组足够长,那么使用AsParallel 就足够了。没有理由添加 Task,因为 PLINQ 会很好地处理并行化。
好的,让我们实际测试一下这段代码。我将迭代一个充满 GUID 的string[]。这是代码:
主要方法:
void Main()
{
//JIT
Test(0);
Test(100);
Test(1000);
Test(10000);
Test(1000000);
Test(10000000);
}
public void Test(int itemAmount)
{
string[] strings = Enumerable.Range(0, itemAmount).Select(i => Guid.NewGuid()
.ToString()).ToArray();
var stopWatch = Stopwatch.StartNew();
CountStringInParallel(strings, itemAmount);
stopWatch.Stop();
Console.WriteLine("Parallel Call: String amount: {0}, Time: {1}",
itemAmount, stopWatch.Elapsed);
stopWatch.Restart();
CountStringSync(strings, itemAmount);
stopWatch.Stop();
Console.WriteLine("Synchronous Call: String amount: {0}, Time: {1}",
itemAmount, stopWatch.Elapsed);
}
并行和同步:
public int CountStringInParallel(string[] s, int i)
{
return s.AsParallel().Count( res => res.Length > i);
}
public int CountStringSync(string[] s, int i)
{
return s.Count(res => res.Length > i);
}
结果:
并行调用:字符串数量:100,时间:00:00:00.0000197
同步调用:字符串数量:100,时间:00:00:00.0000026
并行调用:字符串数量:1000,时间:00:00:00.0000266
同步调用:字符串数量:1000,时间:00:00:00.0000201
并行调用:字符串数量:10000,时间:00:00:00.0002060
同步调用:字符串数量:10000,时间:00:00:00.0002003
并行调用:字符串数量:1000000,时间:00:00:00.0080492
同步调用:字符串数量:1000000,时间:00:00:00.0135279
并行调用:字符串数量:10000000,时间:00:00:00.0744104
同步调用:字符串数量:10000000,时间:00:00:00.1402474
可以看到最多10000个字符串,同步的方式其实比并行的快。