gpt4 book ai didi

c# - 默认构造函数后出现空引用异常

转载 作者:太空宇宙 更新时间:2023-11-03 18:23:26 25 4
gpt4 key购买 nike

我遇到了一个非常奇怪的(对我来说..)异常。它很少发生,但确实...

我的类不是静态的,但只有一个静态属性:

static Dictionary<string, ManualResetEvent> resetEvents = 
new Dictionary<string, ManualResetEvent>();

当我第一次尝试添加重置事件时 - 有时会出现 Null Reference Exception。这可能与尝试添加实例的两个不同线程有关吗?

static ManualResetEvent resetEventsGet(string key)
{
if (resetEvents.ContainsKey(key))
return resetEvents[key];
ManualResetEvent reste = new ManualResetEvent(false);
resetEvents.Add(key, reste); //System.NullReferenceException: 'Object reference not set to an instance of an object.' HOW???
return reste;
}

当我查看“watch”或即时窗口时,任何地方(字典或 resetEvent)都没有 null。

p.s - 我为 visual studio 2017 标记了它,因为它以前从未发生在我身上,尽管代码没有改变。任何想法?谢谢

最佳答案

如果您调用 resetEventsGet 完全有可能来自多个线程。 Dictionary.Add不是线程安全的,当您从多个线程调用它时 - 可能会发生奇怪的事情,包括抛出“NullReferenceException”。使用以下代码重现相对容易:

class Program {
static Dictionary<string, ManualResetEvent> resetEvents = new Dictionary<string, ManualResetEvent>();

static void Main()
{
for (int i = 0; i < 1000; i++) {
new Thread(() =>
{
resetEvents.Add(Guid.NewGuid().ToString(), new ManualResetEvent(false));
})
{
IsBackground = true
}.Start();
}
Console.ReadKey();
}
}

这段代码并不总是,但经常会在 Dictionary.Insert 中抛出空引用异常私有(private)方法。

发生这种情况是因为字典将您的值存储在类似于数组的内部结构中,而这些结构的大小不是固定的。当您添加更多值时 - 字典可能会调整其内部结构的大小,并且当另一个线程已经同时枚举它们时可能会发生调整大小。同时进行调整大小和枚举可能会导致许多不好的事情,包括空引用或索引超出范围异常。

所以永远不要这样做并使用适当的锁定。或者使用专为多线程访问而设计的集合,例如 ConcurrentDictionary<string, ManualResetEvent> .

关于c# - 默认构造函数后出现空引用异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42906995/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com