2009-08-13 41 views
-2

我有線程的列表,我試圖讓我的主線程等待所有線程的列表,終止:任何方式來自動檢查是否存在列表項和列表項上的調用方法?

while (consumers.Count > 0) consumers[0].Join(); 

的問題是,這是不是原子,並我可以得到一個「索引超出範圍」的例外。

是否有任何原子方法來檢查消費者[0]的存在和調用消費者[0] .Join()?

注:我不能做

lock (myLocker) { if (consumers.Count > 0) consumers[0].Join(); } 

,因爲我不想訪問消費者而停留在加入()阻止其他線程。

回答

5

那麼,如果你沒有任何同步在所有但你的應用列表正在從多個線程修改,你已經陷入困境。其他一切都使用myLocker?假如是這樣,怎麼樣:

while(true) 
{ 
    List<Thread> copy; 
    lock (myLocker) 
    { 
     copy = new List<Thread>(consumers); 
    } 
    if (copy.Count == 0) 
    { 
     break; 
    } 
    foreach (Thread thread in copy) 
    { 
     thread.Join(); 
    } 
} 

注意,在佔用鎖,這是你應該做的,到處實現線程安全這個訪問consumers。它也調用Join所有後的副本,而不是隻爲每個迭代做一個。

如果你知道線程不會在此點(例如,它是被排幹一個線程池),您可以消除環路和檢查添加到列表:

List<Thread> copy; 
    lock (myLocker) 
    { 
     copy = new List<Thread>(consumers); 
    } 
    foreach (Thread thread in copy) 
    { 
     thread.Join(); 
    } 
+0

除了我的副本會立即失效。 我想如果線程已經終止thread.Join()會失敗? – mbeckish 2009-08-13 19:38:27

+0

對消費者的所有其他訪問都是同步的。讓我知道如果看到任何其他代碼會有所幫助。 – mbeckish 2009-08-13 19:39:10

+2

@mbeckish:您的副本將總是*在您訪問它時立即失效 - 並且您關於Thread.Join的直覺不正確,如文檔所述:「如果在調用Join時線程已經終止,則該方法立即返回。鑑於你不能原子地「檢查線程狀態並調用Join」任何Join API,如果該線程已經終止,則會由於設計而中斷該異常。 – 2009-08-13 19:40:35

0

假設消費者[0]僅爲空或之類的與預期方法的情況下,你可能只是做

while (consumers.Count > 0) 
    { 
    if (consumers[0] != null) 
     { 
     consumers[0].Join(); 
     } 
    } 
+0

問題的關鍵是,列表*已經*在檢查計數後變爲空。 – 2009-08-13 19:34:08

0

在你的情況下,當你只想等待線程時,爲什麼假設那些線程本身應該從列表中刪除?確保只有主線程可以從列表中刪除線程,在此線程終止後,它不會更改您的設計,並且您可以確定不會訪問不在線的元素。你的循環看起來是這樣的:


for (int i = 0; i < consumers.Count; ++i) 
    consumers[i].Join(); 
//Now that you have joined everyone, just remove reference to your list 
consumers = null; 
相關問題