编辑
2025-09-27
C#
00

目录

摘要
中的并行编程,解释其概念、特点,并通过示例演示其用法。
正文
什么是 Parallel?
Parallel 的特点
示例 1: 并行 for 循环
示例 2: 并行 foreach 循环
示例 3: 并行执行多个方法
示例 4: 并行执行多个方法
Parallel的原理
任务调度器 (Task Scheduler)
工作窃取算法 (Work-Stealing Algorithm)
并行循环分区 (Partitioning)
并行度管理 (Degree of Parallelism)
异常聚合 (Exception Aggregation)
取消支持 (Cancellation Support)

摘要


并行编程是现代软件开发中不可或缺的一部分,特别是在处理大量数据或进行计算密集型任务时。随着多核处理器的普及,C# 语言通过 .NET Framework 提供了强大的并行编程支持。本文将深入探讨 C# 中的并行编程,解释其概念、特点,并通过示例演示其用法。

正文


什么是 Parallel?

System.Threading.Tasks.Parallel 是 .NET Framework 中的一个类,它提供了一组静态方法,用于并行执行循环(Parallel.ForParallel.ForEach)和代码块(Parallel.Invoke)。这些方法可以自动分配任务到多个线程,利用多核处理器的能力,从而提高应用程序的性能。

Parallel 的特点

  • 简化并行代码的编写:Parallel 类提供了简单的 API,使得开发者能够轻松编写并行代码,而不需要深入理解线程管理和同步机制。
  • 动态负载均衡:Parallel 使用任务调度器来动态分配工作负载,可以根据系统的实际运行情况调整线程的使用,以达到最佳性能。
  • 易于集成和使用:Parallel 类与其他 .NET Framework 功能(如LINQ)紧密集成,可以轻松地在现有代码中实现并行操作。
  • 异常处理:Parallel 提供了集中的异常处理机制,可以捕获并行执行代码块中抛出的所有异常。

示例 1: 并行 for 循环

C#
static void Main(string[] args) { Parallel.For(0, 10, i => { Console.WriteLine($"处理迭代 {i} 开始。"); // 模拟工作负载 System.Threading.Thread.Sleep(1000); Console.WriteLine($"处理迭代 {i} 结束。"); }); }

image.png

示例 2: 并行 foreach 循环

C#
static void Main(string[] args) { var items = new List<string> { "苹果", "香蕉", "橙子", "梨" }; Parallel.ForEach(items, item => { Console.WriteLine($"正在处理 {item}。"); // 模拟工作负载 System.Threading.Thread.Sleep(1000); }); }

image.png

示例 3: 并行执行多个方法

C#
static void Main() { Parallel.Invoke( () => DoWork("任务1"), () => DoWork("任务2"), () => DoWork("任务3") ); } static void DoWork(string taskName) { Console.WriteLine($"{taskName} 开始。"); // 模拟工作负载 System.Threading.Thread.Sleep(1000); Console.WriteLine($"{taskName} 结束。"); }

image.png

在这些示例中,Parallel.ForParallel.ForEach 用于并行处理循环迭代,而 Parallel.Invoke 用于并行执行不同的方法调用。这些方法都是在后台自动管理线程和任务,使得开发者能够专注于业务逻辑的实现,而无需担心并行编程的复杂性。

并行编程在处理大量数据或需要大量计算的应用程序中尤其有用,可以显著提高性能和响应速度。然而,开发者在使用时也需要注意线程安全问题,确保共享资源的访问不会导致竞争条件或其他并发问题。

示例 4: 并行执行多个方法

C#
static void Main() { CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); CancellationToken token = cancellationTokenSource.Token; try { cancellationTokenSource.CancelAfter(3000); ParallelOptions parallelOptions = new ParallelOptions(); parallelOptions.CancellationToken = token; // 假设我们有一个需要并行处理的数据集合 int[] data = Enumerable.Range(0, 100).ToArray(); Parallel.ForEach(data, parallelOptions, (item, state) => { // 检查是否有取消请求 if (token.IsCancellationRequested) { // 抛出 OperationCanceledException 来响应取消请求 // 这将导致 Parallel.ForEach 退出 token.ThrowIfCancellationRequested(); } // 模拟一些工作 Console.WriteLine($"Processing item {item}"); Thread.Sleep(1000); // 假装我们在这里做了一些工作 }); } catch (OperationCanceledException ex) { Console.WriteLine("Operation was canceled!"); } Console.ReadKey(); }

image.png

Parallel的原理

Parallel 类的原理基于 .NET Framework 中的任务并行库 (Task Parallel Library, TPL)。TPL 是一种高层次的抽象,用于并行执行代码。它允许开发人员利用多核处理器的能力,通过并行执行来提高应用程序的性能。以下是 Parallel 类原理的几个关键点:

任务调度器 (Task Scheduler)

TPL 使用一个任务调度器来管理任务的执行。默认情况下,它使用线程池 (ThreadPool) 来执行任务,但开发者可以自定义调度器以满足特定需求。任务调度器负责决定何时以及在哪个线程上执行任务。

工作窃取算法 (Work-Stealing Algorithm)

.NET 的线程池实现了一种称为“工作窃取”的算法,其中空闲的线程可以从忙碌的线程“窃取”任务来执行。这有助于动态平衡负载,提高处理器核心的利用率。

并行循环分区 (Partitioning)

Parallel.ForParallel.ForEach 循环会将迭代分成多个区块,这些区块可以独立地在不同的线程上并行执行。TPL 动态决定这些区块的大小,以最小化线程之间的同步开销并优化性能。

并行度管理 (Degree of Parallelism)

TPL 会根据当前系统的资源状况(如 CPU 核心数量)来决定并行度,即同时执行的任务数量。它会尝试最大化 CPU 利用率,同时避免过多的线程创建导致的上下文切换开销。

异常聚合 (Exception Aggregation)

当并行代码块中的多个任务抛出异常时,TPL 会将这些异常聚合到一个 AggregateException 实例中。这使得异常处理变得更加简单,因为开发者只需要处理一个异常实例,即可访问所有抛出的异常。

取消支持 (Cancellation Support)

TPL 与 .NET 的取消框架集成,允许开发者使用 CancellationToken 来取消正在执行的并行操作。

本文作者:技术老小子

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!