2010-04-30 85 views
3

當我收到一些奇怪的行爲......當我在ThreadTest方法遍歷dummyTextList我得到一個索引超出範圍異常(ArgumentOutOfRangeException),但如果我刪除線程和我只是打印出文本,然後一切正常。對於循環索引超出範圍ArgumentOutOfRangeException的多線程

這是我的主要方法:

public static Object sync = new Object(); 
static void Main(string[] args) 
{ 
    ThreadTest(); 
    Console.WriteLine("Press any key to continue."); 
    Console.ReadKey(); 
} 

此方法拋出異常:

private static void ThreadTest() 
{ 
    Console.WriteLine("Running ThreadTest"); 
    Console.WriteLine("Running ThreadTest"); 
    List<String> dummyText = new List<string>() 
    { "One", "Two", "Three", "Four", "Five", 
     "Six", "Seven", "Eight", "Nine", "Ten"}; 

    for (int i = 0; i < dummyText.Count; i++) 
    { 
     Thread t = new Thread(() => PrintThreadName(dummyText[i])); // <-- Index out of range?!? 
     t.Name = ("Thread " + (i)); 
     t.IsBackground = true; 
     t.Start(); 
    } 
} 

private static void PrintThreadName(String text) 
{ 
    Random rand = new Random(DateTime.Now.Millisecond); 
    while (true) 
    { 
     lock (sync) 
     { 
      Console.WriteLine(Thread.CurrentThread.Name + " running " + text); 
      Thread.Sleep(1000+rand.Next(0,2000)); 
     } 
    } 
} 

這並不拋出異常:

private static void ThreadTest() 
{ 
    Console.WriteLine("Running ThreadTest"); 
    List<String> dummyText = new List<string>() 
    { "One", "Two", "Three", "Four", "Five", 
     "Six", "Seven", "Eight", "Nine", "Ten"}; 

    for (int i = 0; i < dummyText.Count; i++) 
    { 
     Console.WriteLine(dummyText[i]); // <-- No exception here 
    } 
} 

有誰知道這是爲什麼發生了什麼?

回答

13

當你傳遞一個局部變量成線或ThreadPool代表通過關閉,你需要把這些變量的副本。如:

for (int i = 0; i < dummyText.Count; i++) 
{ 
    int index = i; 
    Thread t = new Thread(() => PrintThreadName(dummyText[index])); 
    // ... 
} 

如果你不這樣做,那麼基本變量被通過引用傳遞的,而該指數將在for循環的末尾(可能發生超過數組的邊界早在執行封閉之前)。

+2

不應該複製的lambda表達式的外部進行,因爲lambda表達式不會被調用,直到線程真正開始? – 2010-04-30 02:00:18

+0

@Michael YES!就是這樣......只是試了一下就行了。 – Kiril 2010-04-30 02:01:37

+0

@邁克爾:哇,我一定很累,我永遠不會那麼寫!感謝您的快速接觸。 – Aaronaught 2010-04-30 02:02:06