0

0

c# Parallel.ForEach 和分区器(Partitioner)的结合使用

煙雲

煙雲

发布时间:2026-01-11 10:45:02

|

823人浏览过

|

来源于php中文网

原创

Parallel.ForEach 默认采用动态分区策略,线程按需拉取小批量元素(8–64个);显式使用 Partitioner.Create 适用于需连续性、固定块大小、高效范围访问或降低协调开销的场景。

c# parallel.foreach 和分区器(partitioner)的结合使用

Parallel.ForEach 默认如何分区?

默认情况下,Parallel.ForEachIEnumerable 使用的是「动态分区(dynamic partitioning)」策略:不是一次性把整个集合切分成固定几块,而是由线程在运行时按需从源中“拉取”小批量元素(比如 8–64 个),以减少争用和空闲等待。这种策略对大多数顺序可枚举场景够用,但对索引敏感、需局部缓存或 I/O 密集型操作,容易导致负载不均或重复开销。

什么时候必须显式传入 Partitioner.Create?

以下情况建议绕过默认行为,用 Partitioner.Create 显式控制分区逻辑:

  • 源是数组或 IList,且每个分区需保持局部连续性(例如图像分块处理、矩阵行批处理)
  • 需要固定大小的块(如每次处理 1000 条记录,避免某线程只拿到 3 条)
  • 底层数据源本身支持高效范围访问(如数据库游标、内存映射文件),但 IEnumerable 包装后丢失了随机访问能力
  • 想禁用动态分区带来的内部锁和协调开销(尤其在超低延迟场景)

典型写法是:Partitioner.Create(source, true) —— 第二个参数 true 表示启用静态分区(对数组 / 列表自动按索引切分),比默认动态方式更可预测。

Partitioner.Create 的三个重载怎么选?

关键看数据源类型和是否需要自定义逻辑:

intense图片全屏浏览插件(jQuery)
intense图片全屏浏览插件(jQuery)

intense图片全屏浏览插件(jQuery),当鼠标点击图片时,可以全屏幕浏览图片,移动鼠标可以查看图片不同的部分,适合相册展示图片细节。兼容主流浏览器,php中文网推荐下载! 使用方法: 1、head区域引用文件styles.css及intense.js 2、在文件中加入区域代码 3、复制images文件夹

下载
  • Partitioner.Create(TSource[] source, bool loadBalance):最常用。数组 + loadBalance: false → 每个线程分到连续大块;true → 类似默认动态,但基于索引调度
  • Partitioner.Create(IEnumerable source):仅当源本身已实现高效枚举(如自定义 IEnumerator 支持 Reset 或分段)才考虑,否则可能引发重复枚举或线程不安全
  • Partitioner.Create(int fromInclusive, int toExclusive, int rangeSize):纯索引区间分区,适合配合外部数据结构(如 Span 或数组下标计算),不依赖具体集合实例

错误用法示例:对非数组的 List 直接传 Partitioner.Create(list, true) —— 虽然能编译,但 true 参数在此无效,仍走动态路径;应先转成数组或用第三个重载。

分区器 + Parallel.ForEach 的实际性能陷阱

显式分区不等于性能提升,反而可能引入新问题:

  • 分区粒度太粗(如 10 万条一个块):线程数少于 CPU 核心时严重浪费资源;某块耗时远超其他块时整体被拖慢
  • 分区粒度太细(如每块 1 条):抵消并行收益,线程调度和锁开销反超计算收益
  • 误用 Partitioner.Create(source, false) 处理非数组源:触发 NotSupportedException,因为只有数组和某些 IList 实现支持静态索引分区
  • 在分区器内部做重量级初始化(如打开文件、建连接):每个分区执行一次,而非每个线程一次
var data = Enumerable.Range(0, 100000).ToArray();
// ✅ 推荐:固定块大小,每块 1000 项,静态切分
var partitioner = Partitioner.Create(0, data.Length, 1000);
Parallel.ForEach(partitioner, range => {
    for (int i = range.Item1; i < range.Item2; i++) {
        Process(data[i]);
    }
});

真正难的是平衡「局部性」「负载均衡」「初始化成本」三者——多数项目卡在这一步,不是不会写,而是没测过不同 rangeSize 下的吞吐和 GC 行为。

相关专题

更多
php中foreach用法
php中foreach用法

本专题整合了php中foreach用法的相关介绍,阅读专题下面的文章了解更多详细教程。

41

2025.12.04

php中foreach用法
php中foreach用法

本专题整合了php中foreach用法的相关介绍,阅读专题下面的文章了解更多详细教程。

41

2025.12.04

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

315

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

533

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

51

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

194

2025.08.29

treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

533

2023.12.01

C++ 高效算法与数据结构
C++ 高效算法与数据结构

本专题讲解 C++ 中常用算法与数据结构的实现与优化,涵盖排序算法(快速排序、归并排序)、查找算法、图算法、动态规划、贪心算法等,并结合实际案例分析如何选择最优算法来提高程序效率。通过深入理解数据结构(链表、树、堆、哈希表等),帮助开发者提升 在复杂应用中的算法设计与性能优化能力。

17

2025.12.22

c++主流开发框架汇总
c++主流开发框架汇总

本专题整合了c++开发框架推荐,阅读专题下面的文章了解更多详细内容。

78

2026.01.09

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 6.4万人学习

C 教程
C 教程

共75课时 | 4万人学习

C++教程
C++教程

共115课时 | 11.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号