编辑:
我看到你实际上的问题有点误导人,我会尝试回答你想问的问题。在这里,选择使用AsParallel
是一个好的方法,因为实际上没有什么需要await
的。由于你正在处理集合,PLINQ或Paralle.ForEach是一个不错的选择。当你有自然异步I/O绑定操作时,考虑使用async-await
。建议不要用async包装同步方法。
如果你实际测试你的代码,你甚至会惊讶地发现,对这段代码进行并行处理实际上对你的方法执行有负面影响,这取决于你正在迭代的数组的大小。
很多时候人们忘记了使用线程实际上有开销,即使是在使用线程池之外的线程时也是如此。你必须有最少量的CPU密集型工作,这样才值得付出并行化的性能代价。
如果你的数组足够长,则使用AsParallel
就足够了。没有理由添加Task
,因为PLINQ会很好地处理并行化。
好的,让我们测试一下这段代码。我将迭代一个由GUID填充的string[]
。这是代码:
主方法:
void Main()
{
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
你可以看到,在处理不超过10,000个字符串时,同步方法实际上比并行方法更快。
Task
。请参见:http://blog.slaks.net/2014-12-23/parallelism-async-threading-explained/ - SLaks