2011-09-10 47 views
3

我有一個小應用程序,使用BackgroundWorker隨時處理IEnumerator<T> list如何在迭代(C#)時將ListItem添加到列表中?

的代碼基本上是這樣的:

while(true){ 
    foreach(T item in list){ 
     // Process each item and send process 
     // Add an object in child List (List<T1> item.Result) 
    } 
    Thread.Sleep(500); 
} 

現在我有一個按鈕和一個文本框,這將直接添加到的IEnumerator。

問題是,我添加按鈕後,後臺工作人員繼續處理它正在處理項目,但會在完成該項目後停止。它不會繼續。

如何安全地將項目添加到列表中而不影響背景工作?除了後臺工作人員也會添加對象到項目。這應該是什麼解決方案?

謝謝

回答

6

有比原先的名單,不在名單本身的副本背景工人迭代。

while (true) 
{ 
     foreach (T item in new List<T>(list)) 
     { 
      .... 
     } 
     Thread.Sleep(500); 
} 

如果在列舉枚舉時嘗試修改集合,枚舉器將拋出異常。從docs

只要集合保持 不變,枚舉數仍然有效。如果對集合進行了更改(例如添加,修改或刪除元素),則枚舉器無法恢復,並且下一次調用MoveNext或Reset將拋出 InvalidOperationException。如果集合在 MoveNext和Current之間修改,則即使枚舉器已失效,Current也會返回它設置爲的元素 。

+0

是的,但我不修改枚舉器。我正在編輯的是該項目。結果。這不會影響itemList。如果我複製這個。 item.Result不會被修改。 – DucDigital

+1

@Duc - 列表的副本將包含與原始對象相同的對象的引用,所以如果修改副本中的對象,則會修改原始副本(假設T不是值類型)。您詢問了在迭代過程中添加到列表中的情況,這會修改枚舉數的底層集合並使其無效,導致它在下一步移除異常。 – tvanfosson

+0

這個工作很好。謝謝你tvanfosson – DucDigital

1

您可能需要使用「鎖定」的關鍵字,以防止同時放從代碼兩地訪問共享「列表」變量。

http://msdn.microsoft.com/en-us/library/c5kehkcz(v=vs.71).aspx

+0

我只是放了一個鎖。但是該程序將讓用戶等待,直到所有項目完成枚舉後纔將其添加到列表中。它的工作原理,但基本上它不是真正理想的用戶體驗。 :) – DucDigital

2

您應該首先了解關於多線程編程的基礎知識,所以,在這裏就可以了。

嘗試是沿着這樣的:

// shared queue 
ConcurrentQueue<T> queue = new ConcurrentQueue<T>(); 
// shared wait handle 
AutoResetEvent autoEvent = new AutoResetEvent(); 

隊列是更好地在這裏比在列表中,因爲它允許您添加和刪除它的元素,無需擔心當前元素的索引 - 你只是Enqueue()項目另一方面,另一方面,他們也是Dequeue()。使用System.Collections.Concurrent命名空間中的類,該類自動爲您處理線程安全訪問(並且由於複雜的原因,您可能希望稍後閱讀,比簡單的lock()快)。

現在,前臺線程:

// schedule the work 
queue.Enqueue(itemOfWork); 
// and wake up our worker 
autoEvent.Set(); 

這裏的sprinkly魔法的部分是調用我們的WaitHandle(是的,AutoResetEventWaitHandle的實施方案)的Set()。它喚醒了一個等待同步事件觸發的線程,而不使用Thread.Sleep()這樣的醜陋結構。致電Sleep()幾乎總是多線程代碼中的一個錯誤的跡象!

好的,最後一部分 - 工作者線程。這裏沒有多少變化:

while(true) 
{ 
    // wait for the signal 
    autoEvent.WaitOne(); 
    T item; 
    // grab the work item 
    queue.TryDequeue(out item); 

    // handle the item here; 
} 
相關問題