2011-03-01 112 views
1

我在循環中創建線程,按照迭代創建一個線程。在這個線程中,我調用了一個從路徑數組中取得路徑的方法。當我一步一步地運行調試模式時,線程會從路徑數組中調用每個路徑的方法。但是當我正常運行它時,線程會調用具有意外路徑的方法。有些時候,它會使用相同的路徑2次,有時使用相同的路徑。線程for循環!意外的行爲?

代碼有什麼問題?我運行的代碼沒有線程它運行完美,但只有在線程的問題。

下面是代碼:

for (int i = 0; i < appConfigDataPath.Length; i++) 
{ 
     var handle = new EventWaitHandle(false, EventResetMode.ManualReset); 
     string serverPath = appConfigDataPath[i]; 
     string serverName = appConfigDataName[i]; 

     var threadSplit = new Thread(() => 
       { 
        ScanProcess(serverPath, serverName); 
        handle.Set(); 
       }); 
     threadSplit.Start(); 
     waitHandles[i] = handle; 
} 
+0

你應該設置IsBackgroundThread屬性爲true。更重要的是,使用ThreadPool中的線程或使用並行任務來獲得更好的性能。 – 2011-03-01 05:53:06

+0

這只是問題所在。我急於使用線程池或並行進行....我必須使用正常線程執行 – PawanS 2011-03-01 05:57:20

+0

ScanProcess執行什麼操作?它使用數組嗎? – 2011-03-01 06:08:38

回答

1

問題是在實際調用ScanProcess之前更改serverPath。

  1. SERVERPATH = PATH0
  2. startThread0
  3. SERVERPATH = PATH1
  4. thread0:ScanProcess(SERVERPATH,..),SERVERPATH已經PATH1
  5. startThread1
  6. 線程1:ScanProcess(SERVERPATH ,. 。),serverPath仍然是路徑1

您需要傳遞thr中的值儘可能將啓動功能作爲副本。 試試這個:

class Data 
{ 
    public string Path; 
    public string Name; 
    public EventWaitHandle Handle; 
    public Data (string path, string name, EventWaitHandle handle) 
    { 
    Path = path; 
    Name = name; 
    Handle = handle; 
    } 
} 


var threadSplit = new Thread((obj) => 
{ 
    Data data = obj as Data; 
    ScanProcess(data.Path, data.Name); 
    data.Handle.Set(); 
}); 
threadSplit.Start(new Data(serverPath, serverName, handle)); 
3

您需要定義不同,局部變量來保存在每次循環的路徑信息。這個問題是由於在使用帶有外部變量的Lambda表達式時的'閉包'的性質,因爲您在這裏。

如果您在本地聲明serverPathserverName,在循環內而不是外部循環中,它應該按預期工作。

+1

+1,但OP編輯他的問題以顯示在本地聲明的變量。但最初的代碼可能是他正在運行的。 – Josh 2011-03-01 06:14:51

+0

@喬什愛因斯坦 - 看起來像我*可能*他編輯的代碼來嘗試,並沒有奏效。至少,這就是我要做的,要禮貌!我認爲我們需要看到這個impl。該方法雖然。 – 2011-03-01 10:22:28

0

您的serverPathserverName位於線程關閉的外部範圍內。你應該讓他們當地。在循環範圍內聲明它們可以解決這個問題。

+0

不,這不能解決問題 – PawanS 2011-03-01 06:04:01

+0

@GAPS:奇怪。你有沒有試圖把'threadSplit.Start();'放在循環結尾?如果它不能工作,你應該向我們展示'ScanProcess'的實現。 – 2011-03-01 06:16:27

0

我不知道誰在使用waitHandles陣列...但嘗試移動分配.....

var threadSplit = new Thread(() => 
{ 
    ScanProcess(serverPath, serverName); 
    handle.Set(); 
}); 
waitHandles[i] = handle; // assign handle before starting thread. 
threadSplit.Start(); 

編輯:正如其他人注意到(布萊克......我想念他們) serverPath,serverName和句柄必須是本地的。