ConcurrentBag строк и использования .Contains в Parallel.ForEach - PullRequest
0 голосов
/ 20 февраля 2019

Я использую 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 голосов
/ 20 февраля 2019

ConcurrentBag является потокобезопасным, но ваш код не является:

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

Contains будет выполняться потокобезопасным способом, тогда Add также будет выполняться потокобезопасным способом, но у вас нет гарантии, что товар не был добавлен между ними.

Для ваших нужд я рекомендую использовать ConcurrentDictionary.Просто игнорируйте значение, так как оно вам не понадобится.

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

Затем используйте метод TryAdd, чтобы выполнить «если не содержит, то добавить» в одной атомарной операции:

SystemNames.TryAdd(name, true);
...