并发字符串并使用.Contains在Parallel.ForEach中

时间:2019-02-20 17:01:24

标签: c# multithreading concurrency parallel-processing thread-safety

我使用ConcurrentBag包含字符串列表。有时它将包含重复项。

但是,我会在添加新条目之前先检查其内容,因此它永远不应重复。

ConcurrentDictionary<string, string> SystemFiles = PopulateSystemFiles();
ConcurrentBag<string> SystemNames = new ConcurrentBag<string>();

Parallel.ForEach(SystemFiles, file =>
{
    string name = GetSystemName(file.Value);

    if (!SystemNames.Contains(name))
    {
        SystemNames.Add(name);
    }
});

我的假设是.Contains方法不是线程安全的。我说得对吗?

1 个答案:

答案 0 :(得分:3)

ConcurrentBag是线程安全的,但您的代码却不是:

if (!SystemNames.Contains(name))
{
    SystemNames.Add(name);
}

Contains将以线程安全的方式执行,然后Add也将以线程安全的方式执行,但是您不能保证没有在两者之间添加任何项。

根据您的需要,我建议改用ConcurrentDictionary。只需忽略不需要的值即可。

var SystemNames = new ConcurrentDictionary<string, bool>();

然后使用TryAdd方法在单个原子操作中执行“如果不包含则添加”:

SystemNames.TryAdd(name, true);