c# - ConcurrentBag 字符串并在 Parallel.ForEach 中使用 .Contains

标签 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 方法不是线程安全的。我说得对吗?

最佳答案

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

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

Contains 将以线程安全的方式执行,然后 Add 也将以线程安全的方式执行,但您不能保证某个项目没有中间添加了。

根据您的需要,我建议改用 ConcurrentDictionary。忽略该值,因为您不需要它。

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

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

SystemNames.TryAdd(name, true);

关于c# - ConcurrentBag 字符串并在 Parallel.ForEach 中使用 .Contains,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54791721/

相关文章:

c# - 在 C# 中获取 Selenium RemoteWebDriver 的 session ID

c# - ASP.NET Web Api,线程中的数据库连接

c# - 如何使用官方 MongoDB-CSharp-Driver 将条件运算符动态应用于字段?

c# - 检索关闭泛型类型的泛型类型的未封闭类型

android - Runnable 可以返回一个值吗?

ios - Swift:与 DispatchGroup 的死锁

ios - 如何并发更新数组?

java - 跨服务锁定文件

c# - 无法使用 USPS Web Tools API 连接到远程服务器

multithreading - 理解JVM的 "Attach Listener"线程