C#静态构造函数在填充ConcurrentDictionary时初始化线程安全性

本文关键字:初始化 线程 安全性 ConcurrentDictionary 填充 静态 构造函数 | 更新日期: 2023-09-27 18:06:23

我正在呼叫var person = PersonDB.pDict["395096"];

有人能解释一下为什么这个代码会阻塞:吗

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查询的执行停止让我非常不确定。。。

C#静态构造函数在填充ConcurrentDictionary时初始化线程安全性

这是一个静态构造函数死锁。并行线程访问CCD_ 2,该CCD_。将初始化代码移到其他函数。让它返回字典,而不是原地修改pDict

我尽量避免静态构造函数做可能失败的事情。你的代码肯定会失败,因为它是IO。如果失败了,类就会被永久清除。CCD_ 5可以更好。