У меня есть следующий код:
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
Я подключил отладчик и его ноль. _lock действительно нулевой :|
На виндовс 7 х64 работает нормально. Сейчас проверяю другие ОС.
РЕДАКТИРОВАТЬ:
Это связано с десериализацией. После десериализации класса Settings _lock имеет значение null. Поле _lock не существовало во время сериализации настроек и его обратное десериализация как нуль. Удаление сериализованного объектного файла и его воссоздание с устранением исключения поля блокировки. Я проверю, правильно ли это поведение десериализации, если поле не существует при сериализации. Перезапись значения объекта, инициализированного в объявлении, мне не кажется крутым. Но это в значительной степени ответ на это. Я признаю, что я не рассматривал сериализацию, десериализацию в то время, когда я обратился за помощью;).
EDIT2: Вот код, иллюстрирующий мой сценарий и то, что со мной происходило:
Сериализация класса без поля _lock
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 моему полю только для чтения, назначенному при объявлении?
_lock
на ноль? Отметьте поле какreadonly
. Компилятор будет кричать на вас, если вы это сделаете. Если нет, предоставьте короткую, но полную программу, как просит @JonSkeet. - person Sriram Sakthivel   schedule 16.03.2015