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.
多线程计时的不可预测性可能而且似乎会导致问题。
您可以将访问包装在同步构造中,这有时比并发集合更快,但在某些情况下可能不会加快任何速度。正如其他人所提到的,另一种选择是使用像 ConcurrenDictionary
或 ConcurrentQueue
这样的线程安全集合,尽管它们可能会有额外的内存开销。
一定要对你在时间方面获得的任何结果进行基准测试。单线程访问的原始能力有时比处理线程开销更快。线程此代码可能根本不值得。
最后要说的是,HashSet
单独使用,没有同步,对于多线程操作来说是不可接受的。
我有一种方法可以读取每行包含一个 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.
多线程计时的不可预测性可能而且似乎会导致问题。
您可以将访问包装在同步构造中,这有时比并发集合更快,但在某些情况下可能不会加快任何速度。正如其他人所提到的,另一种选择是使用像 ConcurrenDictionary
或 ConcurrentQueue
这样的线程安全集合,尽管它们可能会有额外的内存开销。
一定要对你在时间方面获得的任何结果进行基准测试。单线程访问的原始能力有时比处理线程开销更快。线程此代码可能根本不值得。
最后要说的是,HashSet
单独使用,没有同步,对于多线程操作来说是不可接受的。