Почему этот объект нулевой? - PullRequest
2 голосов
/ 18 ноября 2011

У меня есть класс со статическим полем, как это

public class MyClass
{
    public static Guid MyField1 { get; set; }
}

Тогда у меня есть метод, подобный этому.

public void MyMethod()
{

   MyClass.MyField1  = Guid.NewID();

   Task.Factory.StartNew( () =>  { MyAnotherMethod(MyClass.MyField1);}) ;
}

Проблема в том, что когда я нажимаю вызов MyAnotherMethod (), Я получаю исключение, что «MyClass.MyField1» выдал исключение типа «System.NullReferenceException».Однако, если я заменю вызов Task.Factory.StartNew на приведенный ниже, он будет работать нормально.

ThreadPool.QueueUserWorkItem(MyAnotherMethod, MyClass.MyField1);

Есть идеи?

Ответы [ 2 ]

0 голосов
/ 18 ноября 2011

Существует разница между двумя версиями параллельного вызова метода.В версии Task вы определяете код задачи как лямбда-функцию без аргументов, а внутри вы выполняете код

MyAnotherMethod(MyClass.MyField1);

В версии ThreadPool вы определяете задачу, переданную в ThreadPool, каккод метода MyAnotherMethod, который нужно запустить с начальным параметром MyClass.MyField1.

Если после вызова ThreadPool.QueueUserWorkItem вы каким-либо образом измените MyField1, на запущенную задачу все равно не повлияет, так как MyField1был уже скопирован в стек, и задача начала выполняться.

Если, с другой стороны, вы измените MyField1 после вызова StartNew, возможно, что гонка данных произойдет до вызова метода внутриВозникает метод Task, и метод внутри Task выполняется с другим значением MyField1.Я надеюсь, вы понимаете, что я пытаюсь сказать здесь ...

0 голосов
/ 18 ноября 2011

Я считаю, что это проблема с потоком / кэшированием. В потоке 1 вы присваиваете 11 свойству, но значение находится в кеше, о котором поток 2 не знает (например, он просматривает ОЗУ). Чтобы избежать этой проблемы, вы можете использовать блокировки или указать ключевое слово volatile в своей переменной.

Попробуйте это:

private static volatile int myField1;

public static int MyField1 { get { return myField1; } set { myField1 = value; } }
...