C# 锁字段为空的奇怪情况-可能是.net 4.0 win8-32特定的

C# 锁字段为空的奇怪情况-可能是.net 4.0 win8-32特定的,c#,windows-8,thread-safety,.net-framework-version,C#,Windows 8,Thread Safety,.net Framework Version,我有以下代码: public class Settings { private object _lock = new object(); public void Save() { lock (_lock) { ... } } } 在windows 8 x86/.net 4.0上,锁引发异常: Exception Type: System.ArgumentNullException Except

我有以下代码:

public class Settings
{
    private object _lock = new object();
    public void Save() {
        lock (_lock)
        {
        ...
        }
    }
}
在windows 8 x86/.net 4.0上,锁引发异常:

Exception Type:        System.ArgumentNullException
Exception Message:     Value cannot be null.
Exception Target Site: ReliableEnter 
我附加了调试器及其null_锁实际上是空的:|

在Windows7x64上,它可以正常工作。我正在检查其他操作系统

编辑:

它与反序列化相关。反序列化设置后,类_lock为空_锁定字段在设置序列化时不存在,其返回反序列化为null。删除序列化对象文件并使用锁定字段重新创建该文件消除了异常。如果序列化时字段不存在,我将检查这是否是正确的反序列化行为。覆盖声明中初始化的对象值在我看来并不酷。但这就是答案。我承认在我请求帮助的时候,我没有考虑序列化、反序列化。p> 编辑2: 下面的代码说明了我的情景以及发生在我身上的事情:

序列化不带锁定字段的类

class Program
{
    static void Main(string[] args)
    {
        Settings set = new Settings();

        using (FileStream fs = new FileStream(@"C:\test\tst.set", FileMode.Create, FileAccess.Write, FileShare.None))
        {
            BinaryFormatter bf = new BinaryFormatter();
            bf.Serialize(fs, set);
            fs.Flush();
            fs.Close();
        }
    }
}

[Serializable]
internal class Settings
{
    private int _i = 12;


    public void testMethod()
    {

        int i = 0;
        i++;
        Console.WriteLine(i);

    }
}
反序列化为带有锁定字段的类并调用testMethod:

class Program
{
    static void Main(string[] args)
    {
        Settings set = null;
        using (FileStream fs = new FileStream(@"C:\test\tst.set", FileMode.Open, FileAccess.Read, FileShare.Read))
        {
            BinaryFormatter bf = new BinaryFormatter();
            set = (Settings)bf.Deserialize(fs);
            fs.Flush();
            fs.Close();
        }

        set.testMethod();
    }
}

[Serializable]
internal class Settings
{
    private int _i = 12;
    private readonly object _lock = new object();

    public void testMethod()
    {
        lock (_lock)
        {
            int i = 0;
            i++;
            Console.WriteLine(i);
        }
    }
}
程序将在testMethod调用时崩溃

我在文件中没有发现任何与这种行为有关的东西。我将在反序列化后检查null,这将结束我的麻烦


嗯。反序列化如何将null分配给声明中指定的只读字段?

对于所有意图和目的,如果您将其设置为一个新对象,并且不在其他任何地方更改它,那么您看到的是不可能的

我要尝试的第一件事是将新的目标代码移动到我的构造函数中,如果它在那里感到满意,那么就让它去吧。不管是哪种方式,都要跟踪任务,看看它是否被分配过

确保您的IDE没有监视任何可能作为副作用影响变量值的内容-检查相同内容的条件断点

请注意,您可以在更改时创建条件断点

如果add断言仍然不正确,请在调试中编译-在IDE外部运行

如果调试版本在IDE不是混合的一部分时崩溃,请将其带到其他PC上并尝试

如果它在其他电脑上工作,病毒扫描/重新安装等。内存检查等

编译器可能已损坏,请尝试重新安装Visual Studio


那我就没有主意了

默认情况下,私有属性不会序列化。如果希望序列化它们,则需要创建自定义序列化程序方法


您可以查看以了解更多详细信息

请提供一个简短但完整的程序来演示问题。首先要检查的是您是否将_锁重新分配为null?将该字段标记为只读。如果你这样做,编译器会对你大喊大叫。如果没有,请按照@JonSkeet的要求提供一个简短但完整的程序。这就是我现在有时间做的。屏幕录制:我会尝试建立最小的情况下,我会尽快得到一些时间。完成只读。它最初是只读的。没有其他对_lock.mmm的引用。行为的对象实例是通过反序列化创建的。让我试着建立一些复制的东西。如果你看看我编辑的问题,我将不胜感激。特别是最后一次编辑和最后一行。我唯一能想到的是在_lock上使用[NotSerialized]属性。它不起作用。使用非无菌属性将其设置为null,并使用相同的错误崩溃。您只能尝试最后一个具有非序列化attr的孤立案例。它们已经准备好了。在这个实例之前,我的想法是:由于您必须提供空构造函数或不提供任何构造函数,所以编译器会为类创建一个可序列化的空构造函数,所以我认为反序列化通过构造类的实例来创建类的实例,然后将其字段设置为序列化值。我的印象是,对于只读字段,它不应该这样做。但现在我一点也不知道。顺便说一句,这是可选的技术谈话。在反序列化后,我通过设置新对象的锁来解决问题。不,我不希望它们被序列化。是否有人希望锁序列化?它的只读字段。反序列化如何将其设置为null?或者如何反序列化其未分配声明分配。私有只读对象_lock=新对象;如果你不想被序列化,那么就认为它是在类之外移动的。或添加自定义反序列化逻辑以重新创建它并删除只读位:。这个问题可能会增加更多细节: