2011-11-18 73 views
2

我有一個靜態字段一類這樣的爲什麼此對象爲null?

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); 

任何想法?

+11

MyClass.MyField1不能是'null' - 'int'值類型。你的意思是'0'(零)? – dtb

+0

它不是。 'int'不能是'NULL'(或者'null',因爲它在C#中)。你如何斷定它是'空'? – larsmoa

+3

爲什麼多線程標籤? –

回答

0

我認爲這是一個線程/緩存問題。在線程1中,您將11分配給您的屬性,但該值位於緩存中,而線程2並不知道(例如正在查看RAM)。爲避免此問題,您可以使用鎖定,也可以在變量上指定volatile keyword

試試這個:

private static volatile int myField1; 

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

除了'Factory.StartNew()'應該提供所有需要的內存壁壘。總是避免'揮發性'。 –

+0

這沒有幫助。仍然得到'MyClass.MyField1'拋出了類型'系統的異常。NullReferenceException' –

+0

@palmsnow:請發佈您正在使用的實際代碼,或一個簡短但完整的程序來演示問題。用靜態字段或自動屬性生成NullReferenceException是不可能的! – dtb

0

沒有調用並行方法的兩個版本之間的差異。在任務的版本,你要定義的任務代碼作爲lambda函數沒有參數和內您正在執行的代碼

MyAnotherMethod(MyClass.MyField1); 

在線程池的版本,要定義傳遞給線程池爲代碼的任務方法MyAnotherMethod以初始參數MyClass.MyField1開始。

如果在撥打ThreadPool.QueueUserWorkItem後以某種方式修改MyField1,啓動的任務不會受到影響,因爲MyField1已經複製到堆棧並且任務開始執行。

另一方面,如果您在調用StartNew後修改了MyField1,則在Task方法內發生方法調用之前可能發生數據競爭,並且Task中的方法執行的值不同MyField1。我希望你能理解我在這裏想說的是什麼......