Parallel.ForEach 返回不一致的结果

Parallel.ForEach returning inconsistent result

我有一种方法可以读取每行包含一个 int 值的文本文件,为了加快读取速度,我使用了 Parallel.ForEach,但是我看到的行为是出乎意料的,我有 800 行文件但是当我 运行 这个方法时,每次它 returns 不同的 HashSet 计数,我在搜索后读到的是 Parallel.ForEach 产生多个线程并且它 returns 结果当所有线程都完成了他们的工作,但我的代码执行矛盾,或者我在这里遗漏了一些重要的东西?

这是我的方法:

private HashSet<int> GetKeyItemsProcessed()
{
   HashSet<int> keyItems = new HashSet<int>();

   if (!File.Exists(TrackingFilePath))
     return keyItems;

     // normal foreach works fine

     //foreach(var keyItem in File.ReadAllLines(TrackingFilePath))
     //{
     //    keyItems.Add(int.Parse(keyItem));
     //}


     // this does not return right number of hashset rows
     Parallel.ForEach(File.ReadAllLines(TrackingFilePath).AsParallel(), keyItem =>
     {
         keyItems.Add(int.Parse(keyItem));
     });


    return keyItems;

}

HashSet.Add 不是线程安全的。

来自 MSDN:

Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.

多线程计时的不可预测性可能而且似乎会导致问题。

您可以将访问包装在同步构造中,这有时比并发集合更快,但在某些情况下可能不会加快任何速度。正如其他人所提到的,另一种选择是使用像 ConcurrenDictionaryConcurrentQueue 这样的线程安全集合,尽管它们可能会有额外的内存开销。

一定要对你在时间方面获得的任何结果进行基准测试。单线程访问的原始能力有时比处理线程开销更快。线程此代码可能根本不值得。

最后要说的是,HashSet 单独使用,没有同步,对于多线程操作来说是不可接受的。