有时候我们对大批量数据进行处理,此时并行linq就起作用了.
并行查询
对于以下查询可以耗时会非常大,如下:
const int arraySize = 100000000; var r = new Random(); var a = Enumerable.Range(0, arraySize).Select(x => r.Next(140)); var c = a.Where(x => Math.Log(x) < 4).Select(x => x).Average();
这时候我们可以使用linq中的并行解决方案(使用了AsParallel())
),如果你的CPU支持多核,运行以下代码你会看到效果:
const int arraySize = 100000000; var r = new Random(); var a = Enumerable.Range(0, arraySize).Select(x => r.Next(140)); var c = a.AsParallel(). Where(x => Math.Log(x) < 4). Select(x => x).Average();
我可以附上截图:以下调整之前的运行结果:
以下为调整之后的结果(加了AsParallel())
经过多次测试, 速度基本上快2到3秒,并且我的电脑是i3(两盒的),如果电脑配置更高,或许速度更快.
虽然速度快了,但从图中可以看出占用的CPU和内存也同样提高了,但是对于现在电脑的配置我觉着内存和CPU可以不用考虑了.
取消
.net 提供了一种标准方式,来取消长时间运行的任务,这也适应于并行Linq
var cts = new CancellationTokenSource(); Task.Factory.StartNew(() => { try { var res = (from cc in a.AsParallel().WithCancellation(cts.Token) where Math.Log(cc) < 4 select cc).Average(); Console.WriteLine(res); } catch (OperationCanceledException ex) { Console.WriteLine("3433"); Console.ReadKey(); } }); Console.WriteLine("query start"); Console.Write("cancel?"); string input = Console.ReadLine(); if (input.ToLower().Equals("y")) { cts.Cancel(); }
因为通过Task.Factory.StartNew是创建的异步执行任务,我们在此操作中创建了一个令牌,如果在查询结果出来之前,我们输入了y,那么语句中的查询就不会执行了,这种情况下
多用于查询任务过长的时候使用.