【发布时间】:2021-09-13 06:31:20
【问题描述】:
我有一个文本文件,我将其读入字符串content。为了识别我想要进一步处理的文本体,我获取了字符串中关键字的索引,然后将“起始”索引设置为找到的最小索引。
我用Parallel.ForEach 试过这个...
ConcurrentBag<int> indexes = new();
int index;
switch (Case)
{
case 1:
Parallel.ForEach(KeywordTypes.GetImplementedNamedObjects(), inos =>
{
index = content.IndexOf($"/begin {inos}");
index = index == -1 ? content.Length : index;
indexes.Add(index);
});
index = indexes.Min();
return index;
...和foreach:
foreach (string inos in KeywordTypes.GetImplementedNamedObjects())
{
index = content.IndexOf($"/begin {inos}");
index = index == -1 ? content.Length : index;
indexes.Add(index);
}
index = indexes.Min();
return index;
foreach 会产生预期的结果,但 Parallel.ForEach 不会。
为什么我的代码不是线程安全的?
【问题讨论】:
-
@FranzGleichmann Marc 已经发现了问题。我尝试锁定索引,虽然它是一个线程安全的变量,但完全忘记了 int 索引本身,我在 Parallel.Foreach 中声明它会导致对变量的不安全访问。我这样做是因为我在多个 switch 语句中使用它,这就是它失败的原因。
-
附带说明,如果按插入顺序获取
indexes很重要,您可以从ConcurrentBag<int>切换到ConcurrentQueue<int>。但一般来说,当您想要进行并行工作并且想要返回结果时,PLINQ库(AsParallelLINQ 运算符)比Parallel类更合适。你可以看一个例子here。
标签: c# concurrency thread-safety parallel.foreach