2012-07-26 83 views
3

我的代碼中的任務(t)不能在我的代碼中直接在我的代碼中使用。我得到以下錯誤:動作委託內的任務實例

代碼:

Task t = Task.Factory.StartNew(() => 
{ 
    MessageBox.Show(t.Id.ToString()); 
}); 

現在,如果我做了以下工作:

Task t = null; 
t = Task.Factory.StartNew(() => 
{ 
    MessageBox.Show(t.Id.ToString()); 
}); 

可能有人請解釋爲什麼是這樣的話?

回答

4

C#編譯器不知道什麼關於Task.Factory.StartNew。就編譯器而言,在調用StartNew之後,包括t被分配之前的任何時間,可以在任何時間訪問t

您的第二個代碼片段有競爭條件:如果併發線程上的任務在分配完成之前轉到顯示消息框,您將看到空引用異常。

試試這個實驗:

private static Task Wrapper(Action f) { 
    var res = Task.Factory.StartNew(f); 
    Thread.Sleep(1000); 
    return res; 
} 

現在用的Wrapper在你的第二個片段的調用替換Task.Factory.StartNew直接通話,並觀看了程序崩潰。

Task t = null; 
t = Wrapper(() => { 
    MessageBox.Show(t.Id.ToString()); 
}); 
+0

這兩個片段(在問題中)具有相同的競爭條件。但編譯器不知道,錯誤來自靜態分析。 – 2012-07-26 11:22:59

+0

@HenkHolterman是的,它仍然存在。這個想法是爲了使比賽條件更加明顯。 – dasblinkenlight 2012-07-26 11:23:29

+0

很好的解釋,謝謝。那麼,在代理中訪問我的任務實例有沒有安全的方法? – davenewza 2012-07-26 11:24:38

2

您必須首先爲t分配一個值,以便它獲得對Task類型的對象的引用。

在你的第一批代碼中,你嘗試給t賦一個值並​​在一個語句中使用它(在那裏只有一個分號)。

在第二個示例中,這些是兩個單獨的語句,因此它將起作用。