C#的并行编程通过Parallel类、Task和PLINQ实现多任务同时处理,提升性能。Parallel类适用于独立循环迭代的并行化,如Parallel.ForEach和Parallel.For;Task用于异步操作,配合Task.Run将耗时任务放入线程池,结合async/await保持程序响应性;PLINQ通过.AsParallel()将LINQ查询并行化,适合计算密集型数据处理,可提升大数据集的处理效率。

C#的并行编程,简单来说,就是让你的程序能够同时处理多个任务,从而更充分地利用现代多核处理器的计算能力,以达到提升性能和响应速度的目的。它不是让你的代码“更快”地执行一个任务,而是让它能够“同时”处理多个独立的任务,就像一个团队分工合作,而不是一个人从头到尾包揽所有工作。这背后的核心思想,就是把一个大问题拆解成若干个可以独立解决的小问题,然后让它们并行运行。
解决方案
在C#中,实现并行编程主要依赖于.NET框架提供的
System.Threading.Tasks
命名空间下的工具,尤其是
Parallel
类、
Task
和PLINQ。
Parallel类: 这是最直接、最易用的并行化工具,特别适合处理循环中的独立迭代。当你有一个
for
循环或
foreach
循环,并且每次迭代的操作互不依赖时,
Parallel.For
和
Parallel.ForEach
能让你以最少的代码改动实现并行化。
using System;using System.Collections.Generic;using System.Linq;using System.Threading;using System.Threading.Tasks;using System.Collections.Concurrent; // 用于线程安全集合public class ParallelExample{ public static void Run() { List numbers = Enumerable.Range(1, 1_000_000).ToList(); ConcurrentBag results = new ConcurrentBag(); // 使用线程安全集合 Console.WriteLine("开始使用 Parallel.ForEach 处理大量数据..."); Parallel.ForEach(numbers, num => { // 模拟一个耗时的计算操作 double res = Math.Sqrt(num * num + num); // 注意:这里使用ConcurrentBag是线程安全的,如果使用List.Add()则需要加锁 results.Add(res); }); Console.WriteLine($"Parallel.ForEach 完成,处理了 {results.Count} 个元素。"); // 也可以使用Parallel.For double[] arrayResults = new double[1_000_000]; Parallel.For(0, numbers.Count, i => { arrayResults[i] = Math.Sqrt(numbers[i] * numbers[i] + numbers[i]); }); Console.WriteLine($"Parallel.For 完成,处理了 {arrayResults.Length} 个元素。"); }}
这里有个小陷阱,如果你在
Parallel.ForEach
内部修改共享数据(比如一个普通的
List
),就必须小心处理线程同步问题,否则很可能出现竞态条件导致数据损坏或异常。我这里用了
ConcurrentBag
,它就是专门为多线程环境设计的线程安全集合,能省去手动加锁的麻烦。
Task和Task.Run:
Task
是.NET中表示一个异步操作的核心抽象。
Task.Run
则是一个非常方便的辅助方法,它能将你提供的同步方法(lambda表达式或委托)提交到线程池中执行,并返回一个
Task
对象,你可以用它来跟踪操作的完成情况或获取结果。这对于将耗时操作从主线程(比如UI线程)卸载到后台线程,以保持应用响应性非常有用。
public class TaskExample{ public static async Task Run() { Console.WriteLine("主线程开始执行..."); // 启动一个后台任务,模拟耗时的数据获取 Task fetchDataTask = Task.Run(() => { Console.WriteLine($"Task {Task.CurrentId} 开始模拟获取数据..."); Thread.Sleep(2500); // 模拟2.5秒的耗时操作 Console.WriteLine($"Task {Task.CurrentId} 模拟获取数据完成。"); return "这是从模拟远程服务获取的数据"; }); Console.WriteLine("主线程继续执行其他操作,不被阻塞..."); // 启动多个任务并行执行 List tasks = new List(); for (int i = 0; i { Console.WriteLine($"任务 {taskId} 开始执行..."); Thread.Sleep(new Random().Next(1000, 3000)); // 随机耗时 Console.WriteLine($"任务 {taskId} 执行完成。"); })); } // 等待所有并行任务完成 await Task.WhenAll(tasks); Console.WriteLine("所有并行任务都完成了。"); // 等待第一个任务完成并获取结果 string data = await fetchDataTask; // await会非阻塞地等待任务完成 Console.WriteLine($"主线程获取到数据: {data}"); Console.WriteLine("主线程所有操作完成。"); }}
Task
的强大之处在于它与
async/await
关键字的结合,这让异步编程变得非常自然和易读。你可以用
await
来等待一个
Task
完成,而不会阻塞当前线程,这对于构建响应式UI或高并发的Web服务至关重要。
PLINQ (Parallel LINQ): 如果你的项目中大量使用了LINQ查询,并且这些查询是计算密集型的,PLINQ能让你以声明式的方式轻松实现并行化。你只需要在LINQ查询的开头加上一个
.AsParallel()
方法。
public class PLINQExample{ public static void Run() { List bigNumbers = Enumerable.Range(1, 20_000_000).ToList(); Console.WriteLine("开始使用 PLINQ 进行并行查询..."); // 使用AsParallel()将LINQ查询并行化 var evenNumbersParallel = bigNumbers.AsParallel() .Where(n => n % 2 == 0) .Select(n => n * 2) // 模拟一些计算 .ToList(); Console.WriteLine($"PLINQ 找到并处理了 {evenNumbersParallel.Count} 个偶数。"); // 也可以控制并行度 var limitedParallel = bigNumbers.AsParallel() .WithDegreeOfParallelism(Environment.ProcessorCount / 2) // 只用一半的核心 .Where(n => n % 3 == 0) .ToList
以上就是C#的并行编程是什么?如何使用?的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1439618.html
微信扫一扫
支付宝扫一扫