2010-09-29 29 views
0

我在測試一個簡單的線程池解決方案之前,我把它放入我的應用程序,但我看到的結果對我來說沒有意義。我有一個簡單的表單,只有一個按鈕。此按鈕啓動以下循環:ThreadPool參數

private void button1_Click(object sender, EventArgs e) 
{ 
    MyTestThread oTask = new MyTestThread(); 
    MyThreadInfo oTaskParameters = new MyThreadInfo(); 
    for (int i = 1; i <= 5; i++) 
    { 
     objTaskParameters.MyGuid = Guid.NewGuid(); 
     objTaskParameters.MyNumber = i; 
     ThreadPool.QueueUserWorkItem(new WaitCallback(objTask.ProcessDataForNTime), objTaskParameters); 
    } 
    Console.WriteLine("All threads have been queued for processing..."); 
} 

它調用的類看起來像這樣。它有一個參數MyThreadInfo類,然後MyTestThread類只需循環10秒鐘即可完成。

public class MyThreadInfo 
{ 
    public int MyNumber; 
} 

public class MyTestThread 
{ 
    public void ProcessDataForNTime(Object oParameters) 
    { 
     //We pass parameters 
     MyThreadInfo oThread = (MyThreadInfo)oParameters; 
     int threadNo = oThread.MyNumber; 

     Console.WriteLine("thread {0} started...", threadNo); 

     int iN = 10; //Delay for 10 seconds 
     DateTime dteStart = DateTime.Now; 
     do 
     { 
      System.Threading.Thread.Sleep(1000); //Wait a second before we look again 
     } while (dteStart.AddSeconds(iN) > DateTime.Now); 

     Console.WriteLine("thread {0} completed...", threadNo); 
    } 
} 

我期待這個結果在控制檯/輸出/調試日誌中顯示。當我通過應用程序步驟,我其實看到這一點:

thread 1 started... 
thread 2 started... 
thread 3 started... 
thread 4 started... 
thread 5 started... 
All threads have been queued for processing... 
thread 1 completed... 
thread 2 completed... 
thread 3 completed... 
thread 4 completed... 
thread 5 completed... 

,但如果我全速運行的應用程序,而無需通過代碼或斷點步進,它輸出這樣的:

All threads have been queued for processing... 
thread 5 started... 
thread 5 started... 
thread 5 started... 
thread 5 started... 
thread 5 started... 
thread 5 completed... 
thread 5 completed... 
thread 5 completed... 
thread 5 completed... 
thread 5 completed... 

通過使代碼正常工作的代碼是什麼?我確實注意到向循環中添加Thread.Sleep(1000)(1秒)確實會強制應用程序正確標記線程,但我正在嘗試開發一個快速多線程應用程序,並添加1秒延遲每個線程都令人沮喪。

有人可以給我一些見解,爲什麼我看到這種行爲?

感謝...

山姆

回答

6

您需要將每一個新的線程一個全新的對象。目前,他們都得到製作MyNumber可設置爲PARAM上MyThreadInfo構造後的引用在主線程中的同一個對象,即oTaskParameters

試試這個,:

for (int i = 1; i <= 5; i++) 
{ 
    MyThreadInfo oTaskParameters = new MyThreadInfo(i); 
    objTaskParameters.MyGuid = Guid.NewGuid(); 
    ThreadPool.QueueUserWorkItem(new WaitCallback(objTask.ProcessDataForNTime), objTaskParameters); 
} 

MyThreadInfo(int i) : MyNumber(i) 
{ 
    // rest of construction logic 
} 

這一變化意味着,每一個新的線程得到MyThreadInfo的一個不相交的實例,該線程的ID適當地設置。

仍然不能保證線程將按升序打印出它們的ID。您必須引入某種類型的FIFO隊列/處理來執行該操作。有關於該問題ordering of thread execution using Threadpool.QueueUserWorkItem的詳細討論。

+0

完美。我並不擔心訂單,只是能夠在發生時識別這些線索。謝謝你的幫助! – Sam 2010-09-29 13:38:43

+0

@Sam - 很高興這有幫助 – 2010-09-29 13:39:45