在现代 C# 开发中,并行编程是提升程序性能的重要手段。.NET 提供了 Parallel.ForEach 等高级 API 来简化多线程任务,但默认的分区策略并不总是最优的。这时,C# 自定义并行分区器 就派上用场了!本文将手把手教你如何创建、测试并理解自定义分区器,即使你是初学者也能轻松上手。

在 Parallel.ForEach 中,.NET 需要将数据源“分割”成多个块,分配给不同的线程处理。这个“分割”的逻辑就是由分区器(Partitioner)控制的。
默认情况下,.NET 会根据数据类型(如数组、List)自动选择分区策略。但对于某些特殊场景(例如处理大对象、非均匀数据或自定义集合),默认策略可能导致负载不均,影响性能。此时,我们可以通过 System.Collections.Concurrent.Partitioner 类来自定义分区行为。
假设我们要处理一个整数列表,但希望每个线程每次只处理固定数量的元素(比如 3 个)。我们可以继承 Partitioner<T> 并重写关键方法。
using System;using System.Collections.Concurrent;using System.Collections.Generic;using System.Threading.Tasks;public class ChunkPartitioner<T> : Partitioner<T>{ private readonly IList<T> _source; private readonly int _chunkSize; public ChunkPartitioner(IList<T> source, int chunkSize) { _source = source ?? throw new ArgumentNullException(nameof(source)); _chunkSize = chunkSize > 0 ? chunkSize : throw new ArgumentOutOfRangeException(nameof(chunkSize)); } // 表示是否支持动态分区(通常返回 false) public override bool SupportsDynamicPartitions => false; // 返回一个可枚举的分区集合 public override IList<ILookup<int, T>> GetPartitions(int partitionCount) { var partitions = new List<ILookup<int, T>>(partitionCount); for (int i = 0; i < partitionCount; i++) { partitions.Add(null!); // 占位 } return partitions; } // 核心方法:返回每个分区的枚举器 public override IEnumerable<IEnumerable<T>> GetDynamicPartitions() { throw new NotSupportedException("此分区器不支持动态分区。"); } // 实现静态分区(推荐用于已知线程数的场景) public override IList<IEnumerable<T>> GetPartitions(int partitionCount) { var partitions = new List<IEnumerable<T>>(partitionCount); for (int i = 0; i < partitionCount; i++) { partitions.Add(GetChunk(i, partitionCount)); } return partitions; } private IEnumerable<T> GetChunk(int partitionIndex, int partitionCount) { int startIndex = partitionIndex * _chunkSize; int endIndex = Math.Min(startIndex + _chunkSize, _source.Count); for (int i = startIndex; i < endIndex; i++) { yield return _source[i]; } }}现在我们来编写一个测试程序,验证分区器是否按预期工作:
class Program{ static void Main() { var data = Enumerable.Range(1, 20).ToList(); // [1, 2, ..., 20] var partitioner = new ChunkPartitioner<int>(data, chunkSize: 4); Console.WriteLine("开始并行处理..."); Parallel.ForEach( partitioner, (chunk) => { var threadId = Task.CurrentId ?? 0; foreach (var item in chunk) { Console.WriteLine($"线程 {threadId} 处理: {item}"); Thread.Sleep(100); // 模拟耗时操作 } }); Console.WriteLine("处理完成!"); }}运行这段代码,你会看到输出结果中,每个线程连续处理 4 个数字(最后一个线程可能少于 4 个)。这说明我们的 C# 自定义并行分区器 成功控制了数据分块逻辑。
使用自定义分区器前,建议先用默认方式测试性能。只有在确认存在负载不均或性能瓶颈时,才考虑自定义。此外:
Parallel.ForEach,优先使用静态分区(即重写 GetPartitions(int))通过本教程,你已经掌握了如何在 C# 中实现和测试 .NET 并行编程教程 中的关键组件——自定义分区器。无论是优化现有系统,还是应对复杂数据处理场景,这项技能都将助你一臂之力。记住,Parallel.ForEach 自定义分区 的核心在于“按需分块”,合理使用能显著提升程序效率。
如果你正在寻找更多 C# Partitioner 示例,可以查阅 Microsoft 官方文档或尝试扩展本文中的 ChunkPartitioner 支持动态分区、范围分区等高级功能。
Happy Coding with C# and Parallelism! 🚀
本文由主机测评网于2025-12-05发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://www.vpshk.cn/2025123296.html