2013-12-10 39 views
4

我想要做的事情非常簡單,
我掃描了一個字符串列表,然後將每個字符串傳遞給一個新線程進行打印。將每個列表項目逐一傳遞給新線程

using System; 
using System.Collections.Generic; 
using System.Threading; 

namespace MultithreadingSynchronization 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      List<string> stringList = new List<string> { "server1", "server2", "server3", "server4", "server5", "server6", "server7", "server8", "server9"}; 

      foreach (string server in stringList) 
      { 
       ThreadStart work = delegate { Threadjob(server); }; 
       new Thread(work).Start(); 
       //Thread.Sleep(10); // 10 ms delay of main thread 
      } 
     } 

     public static void Threadjob(object server) 
     { 
      Console.WriteLine(server); 
     } 
    } 
} 

從某些原因,還有接受錯誤的值,因此,輸出提出了一些重複的字符串,也錯過了一些串線。
我期待這個輸出(順序並不重要):

server1 
server2 
server3 
server4 
server5 
server6 
server7 
server8 
server9 

但是,有時我得到這樣的:

server3 
server2 
server5 
server5 
server7 
server4 
server8 
server9 
server9 

,有時我得到這個:

server2 
server2 
server4 
server3 
server6 
server7 
server7 
server8 
server9 

事實上,如果我在每個線程創建後放一個延遲,我會得到我期望得到什麼。

有什麼想法?

+0

我曾嘗試你的代碼(vs2012 C#控制檯應用程序默認設置,win8.0 64) - 我從來沒有重複的數字。 - 我確實按照您所期望的使用多線程的方式將它們亂序排列,但不能重複。 –

+0

難道你不想讓你的ThreadJob方法成爲一個實例方法嗎?它似乎不是線程安全的 –

+1

這是因爲循環變量。 [關閉循環變量被認爲是有害的](http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx)。更改爲for循環或使用本地foreach變量,如oakio所示。 – Patrick

回答

2

您應該製作變量的本地副本。 試試這個:

foreach (string server in stringList) 
    { 
     string local = server; 
     ThreadStart work = delegate { Threadjob(local); }; 
     new Thread(work).Start(); 
     //Thread.Sleep(10); // 10 ms delay of main thread 
    } 

此處瞭解詳情:Captured variable in a loop in C#

+0

如果你發現一個重複的問題,你應該投票/標記以重複的方式關閉它,而不是發佈一個答案。 – Servy

+0

非常感謝!它解決了我的問題! – elady

2
new Thread(Threadjob).Start(server); 

完成!但是,使用任務而不是線程可能更合適 - 或者至少使用ThreadPool。

+0

它也解決了我的問題,謝謝! – elady

1

好吧,我想我明白了。
Froeach循環持有一個指針,並在每次迭代中更改它。 有時,線程已創建,但仍未運行。同時,循環在接下來的迭代中更改指針,並且當線程開始其作業時,它將獲取當前指針的值(後續字符串)。

順便說一句,我找到了另一種解決方案here,如何將參數傳遞給線程的主要功能,所以我定我的循環,它工作正常現在

foreach (string server in stringList) 
{ 
    Thread thread1 = new Thread(new ParameterizedThreadStart(Threadjob)); 
    thread1.Start(server); 
}