You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Parallel.ForEach中使用Regex.EnumerateMatches的ref struct枚举器?

解决Regex源生成器ref struct枚举器无法并行的问题

问题背景

为追求性能使用了Regex源生成器,其EnumerateMatches(span)方法返回ref struct枚举器,无法用于Parallel.ForEach等并行构造。需填充一个含100个结构体的数组,数组结构为value[0] -> padding[1] -> value[2] -> padding[3] -> ...(共50个value槽、50个padding槽),其中padding槽的填充依赖前后两个value槽的位置信息,希望通过并行化提升填充效率。

解决方案

核心思路

ref struct枚举器无法跨线程传递,因此先将所有匹配结果预收集到普通非值类型集合中,再分两个阶段并行填充数组:

  1. 并行填充所有value槽:每个value槽仅依赖对应的匹配结果,互相无依赖,可安全并行。
  2. 并行填充所有padding槽:待所有value槽填充完成后,每个padding槽仅依赖其前后的value槽,互相无依赖,也可安全并行。

代码实现

// 1. 预收集所有匹配结果到List,避开ref struct枚举器的跨线程限制
SpanRegexSrc regex = SpanRegexSrc.CachedRegex;
var matches = regex.EnumerateMatches(myString.AsSpan()).ToList();

// 2. 并行填充value槽(索引为0,2,4,...,98)
Parallel.For(0, matches.Count, matchIndex =>
{
    int valueSlotIndex = 2 * matchIndex;
    FillValueSlot(matches[matchIndex], ref _array[valueSlotIndex]);
});

// 3. 并行填充padding槽(索引为1,3,5,...,99)
Parallel.For(1, _array.Length, 2, padSlotIndex =>
{
    FillPadSlot(_array, padSlotIndex);
});

注意事项

  • 数组中每个索引仅被单个线程操作,无线程安全问题。
  • 若匹配结果与value槽的对应关系不同(比如每个匹配对应两个value槽),只需调整valueSlotIndex的计算逻辑即可,核心流程不变。
  • 针对100个元素的数组,并行带来的性能提升可能有限,但该方案可无缝扩展到更大规模的数组。

内容的提问来源于stack exchange,提问作者Shpendicus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 22:17:53