Я звоню var person = PersonDB.pDict["395096"];
C# статический конструктор безопасности инициализации нити при заполнении ConcurrentDictionary
Может кто-нибудь объяснить мне, почему этот код блоки:
static class PersonDB
{
internal static readonly ConcurrentDictionary<string, Person> pDict;
static PersonDB()
{
pDict = new ConcurrentDictionary<string, Person>();
var headers = File.ReadLines(FindPath.DataSetPerson).First().Split(';');
File.ReadLines(FindPath.DataSetPerson).AsParallel().Skip(1).Select(s => s.Split(';')).ForAll(fa =>
pDict.TryAdd(fa[0], new Person() { all = Enumerable.Range(0, fa.Length).ToDictionary(t => headers[t], d => fa[d]) })
);
}
}
sealed class Person
{
public Dictionary<string, string> all;
}
В то время как эта часть не блок:
static class PersonDB
{
internal static readonly ConcurrentDictionary<string, Person> pDict;
static PersonDB()
{
pDict = new ConcurrentDictionary<string, Person>();
var headers = File.ReadLines(FindPath.DataSetPerson).First().Split(';');
//File.ReadLines(FindPath.DataSetPerson).AsParallel().Skip(1).Select(s => s.Split(';')).ForAll(fa =>
// pDict.TryAdd(fa[0], new Person() { all = Enumerable.Range(0, fa.Length).ToDictionary(t => headers[t], d => fa[d]) })
//);
Parallel.ForEach(File.ReadLines(FindPath.DataSetPerson).Skip(1).Select(s => s.Split(';')), line =>
{
pDict.TryAdd(line[0], new Person() { all = Enumerable.Range(0, line.Length).ToDictionary(t => headers[t], d => line[d]) });
});
}
}
sealed class Person
{
public Dictionary<string, string> all;
}
Честно говоря, я даже не уверен, что последний теперь потокобезопасен, но, по крайней мере, он работает без проблем. Я хотел бы знать, как сделать PersonDB потокобезопасным классом таким образом, чтобы не было условий гонки или тупиков. PDict необходимо создать один раз при использовании pDict. Я думал, что статический конструктор был хорошим решением для этого, но остановка выполнения в запросе PLINQ делает меня очень неуверенным ...
Пропуск (1) может пропустить любую строку, потому что ваш запрос не упорядочен. – usr
Все это, вероятно, спорный, потому что CD гораздо медленнее, чем обычный словарь. Просто используйте обычный словарь, и он будет быстрее. * Возможно, анализ синтаксиса CSV может выиграть от параллелизма, но при высоких накладных расходах. – usr
Пропустить (1), чтобы просто пропустить заголовок файла csv, заполнение обычного словаря с помощью параллельного foreach заставляет параллельные потоки записывать в словарь одновременно, что вызывает ошибки, поэтому здесь необходим параллельный запрос (но исправьте меня если я ошибаюсь, я не эксперт в этом) – BigChief