Estou com problemas com um programa em que preciso gerar relatórios simultaneamente em várias threads. É um programa legado, o código não está bem documentado e gera um erro ao executar testes NUnit, mas não ao executar o aplicativo localmente no IIS ou em uma máquina Windows Server dedicada com IIS. A primeira coisa que me chama a atenção é o código a seguir. Pelo que entendi, DEVERIA SER THREAD-SEGURO, mas não tenho 100% de certeza.
public static class Transliterator
{
private static readonly ConcurrentDictionary<SupportedConversions, ConcurrentDictionary<char, string>> converters = new ConcurrentDictionary<SupportedConversions, ConcurrentDictionary<char, string>>
{
[SupportedConversions.MK_ENG] = new ConcurrentDictionary<char, string>()
{
['а'] = "a"
, ['б'] = "b"
, ['в'] = "v"
, ['г'] = "g"
, ['д'] = "d"
, ['ѓ'] = "gj"
, ['е'] = "e"
, ['ж'] = "zh"
, ['з'] = "z"
, ['ѕ'] = "dz"
, ['и'] = "i"
, ['ј'] = "j"
, ['к'] = "k"
, ['л'] = "l"
, ['љ'] = "lj"
, ['м'] = "m"
, ['н'] = "n"
, ['њ'] = "nj"
, ['о'] = "o"
, ['п'] = "p"
, ['р'] = "r"
, ['с'] = "s"
, ['т'] = "t"
, ['ќ'] = "kj"
, ['у'] = "u"
, ['ф'] = "f"
, ['х'] = "h"
, ['ц'] = "c"
, ['ч'] = "ch"
, ['џ'] = "dzh"
, ['ш'] = "sh"
, ['А'] = "A"
, ['Б'] = "B"
, ['В'] = "V"
, ['Г'] = "G"
, ['Д'] = "D"
, ['Ѓ'] = "Gj"
, ['Е'] = "E"
, ['Ж'] = "Zh"
, ['З'] = "Z"
, ['Ѕ'] = "Dz"
, ['И'] = "I"
, ['Ј'] = "J"
, ['К'] = "K"
, ['Л'] = "L"
, ['Љ'] = "Lj"
, ['М'] = "M"
, ['Н'] = "N"
, ['Њ'] = "Nj"
, ['О'] = "O"
, ['П'] = "P"
, ['Р'] = "R"
, ['С'] = "S"
, ['Т'] = "T"
, ['Ќ'] = "Kj"
, ['У'] = "U"
, ['Ф'] = "F"
, ['Х'] = "H"
, ['Ц'] = "C"
, ['Ч'] = "Ch"
, ['Џ'] = "Dzh"
, ['Ш'] = "Sh"
}
};
public static string Transliterate(string source, SupportedConversions conversion)
{
ConcurrentDictionary<char, string> converter = converters[conversion];
var result = new StringBuilder();
foreach (char letter in source)
{
if (converter.TryGetValue(letter, out string convertedLetter))
{
result.Append(convertedLetter);
}
else
{
result.Append(letter);
}
}
return result.ToString();
}
public enum SupportedConversions
{
MK_ENG = 0
}
}
A maioria das coleções simples é perfeitamente segura para threads, desde que todas as threads estejam apenas lendo a coleção. O exemplo publicado nunca altera nada no dicionário após a criação, portanto, seria seguro para threads mesmo sem usar um Dicionário Simultâneo. Consulte a documentação do Dicionário.
Se esse for o caso, você pode considerar usar ImmutableDictionary ou ReadOnlyDictionary para deixar mais claro que os dicionários nunca mudam.
Se você estiver alterando algo no dicionário, seu resultado pode depender da ordem de execução. Nesse caso, um dicionário concorrente não o salvará, apenas garantirá que as operações do dicionário sejam thread-safe. Há muitas maneiras pelas quais condições de corrida ou outros problemas de threading podem arruinar seu dia. Para lidar com esses problemas, você pode precisar de bloqueios ou outra sincronização em um nível mais alto.