2011-10-23 48 views
1

當我運行下面的代碼片段時,拋出了IndexOutOfRangeException。看起來,當拋出異常時,我是2。我的理解是,新的線程在i的值被改變後開始。有沒有辦法讓這個代碼安全的這種問題?啓動新線程時拋出IndexOutOfRangeException

int x[2] = {1, 3}; 
int numberOfThreads = 2; 

for (int i = 0; i < numberOfThreads; i++) 
{ 
    new Thread(() => 
    { 
     DoWork(x[i]); 
    }).Start(); 
} 
+0

可能重複: //stackoverflow.com/questions/2741870/for-loop-index-out-of-range-argumentoutofrangeexception-when-multithreading) –

回答

6

的問題是變量i被捕獲,並通過線程實際得到啓動的時候,它的2

用這個代替:

for (int i = 0; i < numberOfThreads; i++) 
{ 
    int value = x[i]; 
    new Thread(() => DoWork(value)).Start(); 
} 

或者:

foreach (int value in x) 
{ 
    int copy = value; 
    new Thread(() => DoWork(copy)).Start(); 
} 

或者:

for (int i = 0; i < numberOfThreads; i++) 
{ 
    int copyOfI = i; 
    new Thread(() => DoWork(x[copyOfI])).Start(); 
} 

在每種情況下,λ表達式將捕獲在循環的每次迭代的新變量 - 這不會通過隨後的迭代改變的變量。

一般來說,您應該避免捕獲將在稍後執行的lambda表達式中的循環變量。有關更多詳細信息,請參閱Eric Lippert's blog post

從C#5開始,很可能會更改foreach循環行爲以避免這成爲問題 - 但for循環等效仍將是一個問題。

2

您關閉了循環變量,以獲得電流值的i使用,而不是一個本地副本:

for (int i = 0; i < numberOfThreads; i++) 
{ 
    int localI = i; 
    new Thread(() => 
    { 
     DoWork(x[localI]); 
    }).Start(); 
} 
[For循環索引超出範圍ArgumentOutOfRangeException的多線程時(HTTP的
相關問題