var numbers = new List<int> { 1, 2, 3, 4, 5 }; var evenNumbers = numbers.Where(n => n % 2 == 0).ToList(); foreach (var number in evenNumbers) { Console.WriteLine(number); // 输出: 2, 4 }LINQ 使用简单,非常适合处理小型到中型数据集或计算量不大的查询。
var numbers = Enumerable.Range(1, 10_000); var evenNumbers = numbers.AsParallel() .Where(n => n % 2 == 0) .ToList(); Console.WriteLine(evenNumbers.Count); // 输出: 5000调用 AsParallel() 方法后,查询将会在多个处理器核心上并行执行。
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; classProgram { static void Main() { var largeDataSet = Enumerable.Range(1, 5_000_000).ToList(); // LINQ 测试 var stopwatch = Stopwatch.StartNew(); var linqPrimes = largeDataSet.Where(IsPrime).ToList(); stopwatch.Stop(); Console.WriteLine($"LINQ 时间: {stopwatch.ElapsedMilliseconds} 毫秒"); Console.WriteLine($"LINQ 素数数量: {linqPrimes.Count}"); // PLINQ 测试 stopwatch.Restart(); var plinqPrimes = largeDataSet.AsParallel().Where(IsPrime).ToList(); stopwatch.Stop(); Console.WriteLine($"PLINQ 时间: {stopwatch.ElapsedMilliseconds} 毫秒"); Console.WriteLine($"PLINQ 素数数量: {plinqPrimes.Count}"); } static bool IsPrime(int number) { if (number <= 1) returnfalse; for (int i = 2; i <= Math.Sqrt(number); i++) { if (number % i == 0) returnfalse; } returntrue; } }基准测试说明
// 堆代码 duidaima.com var numbers = Enumerable.Range(1, 10); var orderedResult = numbers.AsParallel() .AsOrdered() .Where(n => n % 2 == 0) .ToList(); Console.WriteLine(string.Join(", ", orderedResult)); // 输出: 2, 4, 6, 8, 10如果结果顺序无关紧要,可以使用 .AsUnordered() 进一步优化性能。
var numbers = Enumerable.Range(1, 1_000_000).ToList(); var stopwatch = Stopwatch.StartNew(); // 有序 PLINQ var orderedPrimes = numbers.AsParallel() .AsOrdered() .Where(IsPrime) .ToList(); stopwatch.Stop(); Console.WriteLine($"AsOrdered 执行时间: {stopwatch.ElapsedMilliseconds} 毫秒"); stopwatch.Restart(); // 无序 PLINQ var unorderedPrimes = numbers.AsParallel() .AsUnordered() .Where(IsPrime) .ToList(); stopwatch.Stop(); Console.WriteLine($"AsUnordered 执行时间: {stopwatch.ElapsedMilliseconds} 毫秒");预期输出(示例):
AsOrdered 执行时间: 210 毫秒 AsUnordered 执行时间: 140 毫秒可以看到,无序执行通常会更快,因为它省去了保持顺序所需的额外开销。
4.程序运行在多核 CPU 的环境中,能充分利用多线程优势。
特性 | LINQ | PLINQ |
---|---|---|
执行方式 | 顺序执行 | 并行执行 |
性能优势 | 适合小型数据集 | 针对大型数据集优化 |
CPU 利用率 | 使用单个核心 | 使用多个核心和线程 |
顺序保持 | 默认保持输入顺序 | 默认无序,可通过 AsOrdered() 强制有序 |
错误处理 | 错误传播较简单 | 需要处理线程级别的异常 |
控制能力 | 控制执行方式有限 | 支持取消、分区等高级控制选项 |
系统开销 | 几乎无额外开销 | 线程管理和分区可能带来一定开销 |