Подтвердить что ты не робот

Является ли поток экземпляров Regex безопасным для совпадений в С#

У меня есть это регулярное выражение, которое я использую в Parallel.ForEach<string>. Это безопасно?

Regex reg = new Regex(SomeRegexStringWith2Groups);
Parallel.ForEach<string>(MyStrings.ToArray(), (str) =>
{
    foreach (Match match in reg.Matches(str)) //is this safe?
        lock (dict) if (!dict.ContainsKey(match.Groups[1].Value))
            dict.Add(match.Groups[1].Value, match.Groups[2].Value);
});
4b9b3361

Ответ 1

Regex объекты доступны только для чтения и, следовательно, являются потокобезопасными. Это их возвраты, объекты Match, которые могут потенциально вызвать проблемы. MSDN подтверждает это:

Сам класс Regex является потокобезопасным и неизменным (только для чтения). То есть, объекты Regex могут быть созданы в любом потоке и разделены между потоками; методы сопоставления можно вызывать из любого потока и никогда не изменять глобальное состояние.

Однако объекты результатов (Match и MatchCollection), возвращаемые Regex, должны использоваться в одном потоке.

Я был бы обеспокоен тем, как создается коллекция Match, которая может быть параллельной, что может привести к тому, что коллекция будет выглядеть странно. В некоторых реализациях совпадений используется отложенная оценка, что может привести к некоторому сумасшедшему поведению в этом цикле foreach. Я бы, вероятно, собирал все матчи, а затем оценивал их позже, чтобы быть в безопасности и добиваться согласованной производительности.