2012-04-16 88 views
15

情景:在一個循環的異步任務執行包含在程序改變參數的方法繼續:將更改值的參數傳遞給任務 - 行爲?

while(this._variable < 100) 
{ 
    this._variable++; 
    var aTask = Task.Factory.StartNew(() => 
    { 
     aList.add(this._variable); 
     update(this._savePoint); 
    }); 
} 

如果循環的運行速度比完成任務快,將在列表中添加變量的當前值或是本地保存的變量並添加了原始值?

+3

Jon Skeet檢查了這個:http://csharpindepth.com/Articles/Chapter5/Closures.aspx – 2012-04-16 18:51:55

+0

+1優秀的問題! – nawfal 2012-04-16 19:25:28

回答

11

閉合關閉變量,而不是值。因此,遞增_variable可以改變引用它的任務的行爲。

可以防止這種通過建立一個本地副本:

while (this._variable < 100) 
{ 
    this._variable++; 
    int local = _variable; 
    var aTask = Task.Factory.StartNew(() => 
    { 
     aList.add(local); 
     update(this._savePoint); 
    }); 
} 

或者你可以傳遞價值的任務,狀態:

while (this._variable < 100) 
{ 
    this._variable++; 
    var aTask = Task.Factory.StartNew(object state => 
    { 
     aList.add((int)state); 
     update(this._savePoint); 
    }, this._variable); 
} 

這些都通過複製_variable的值工作一個新的臨時變量。在第一種情況下,local變量是在循環範圍內定義的,因此每次迭代都會得到一個新變量。在第二種情況下,您將_variable的值作爲state參數傳遞給任務時,複製該值。如果_variable是引用類型,這些解決方案將不起作用;你必須執行一個克隆。

+0

如果變量是一個類的實例呢?循環中的SomeClass localVariable = this._variable。作爲參考,你如何確保你不會收到改變的狀態。 – asunrey 2012-04-17 14:37:44

+1

@Moyler:你必須克隆循環內的實例,這意味着你創建一個新的實例,並使其屬性的值與原始實例的值相同。 – 2012-04-17 14:50:48

+0

謝謝,我需要證實。此外,我最初的意思是我的例子有一個引用類型。很高興能得到一筆兩筆一筆的交易。 – asunrey 2012-04-17 15:16:15

相關問題