I'm calling var person = PersonDB.pDict["395096"];
Can anyone explain me why this code blocks:
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;
}
While this part does not block:
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;
}
To be honest I'm not even sure if the latter is thread safe now, but at least it runs without problems. I would like to know how to make the PersonDB a thread safe class in such a way that there will be no race conditions or deadlocks. The pDict needs to be created once on usage of the pDict. I thought the static constructor was a nice solution for this but the execution stop on the PLINQ query makes me very unsure...
This is a static constructor deadlock. The parallel threads access PersonDB
which blocks until PersonDB
is statically initialized. Move the initialization code to a different function. Make it return the dictionary instead of modifying pDict
in place.
I try to avoid static constructors that do things that can fail. Your code certainly can fail because it is IO. If it does the class is permanently hosed. Lazy
can be better.