2012-01-07 181 views
0

在列表(結構),我一直在使用這個代碼modifiy項財產

Private Sub ChangeState(ByVal ww As WebWorker, _ 
         ByVal NewState As WorkerState) 
     Dim oWBB As WebWorker = ListWebWorkers.Find(Function(item As WebWorker) item.Browser.Name.ToLower = ww.Browser.Name.ToLower) 
     If oWBB.Browser IsNot Nothing Then 
      ListWebWorkers.Remove(oWBB) 
      oWBB = ww 
      oWBB.State = NewState 
      ListWebWorkers.Add(oWBB) 
     End If 
    End Sub 

到modifiy項目的屬性(結構)列表,但是這個給問題,當兩個或兩個以上的項目調用這個子程序。其中一件物品可能已被刪除。此代碼在UI線程中執行,並且必須是

那麼有沒有更好的方法來修改列表結構中的項目?

謝謝

+0

爲什麼WebWorker是結構而不是類? – 2012-01-07 18:02:18

+0

@ Meta-Knight在課堂上有什麼不同,有什麼優勢? – Smith 2012-01-07 18:32:19

+0

如果WebWorker是一個類,則不需要刪除並再次添加該項目。最好的做法是幾乎總是使用一個類,除非你有一個不可變的數據結構。 – 2012-01-07 19:53:08

回答

1

在你現在的代碼,你不檢查是否存在正確的項目(要檢查oWBB.Browser,但你應該檢查oWBB。此外,它不是線程安全的。

會更容易驗證的項目存在的線程安全的方式,如果你使用一個ConcurrentDictionary代替

這裏是重寫代碼的一個例子:

' Create a dictionary with case-insensitive keys 
Private Shared ListWebWorkers As New System.Collections.Concurrent.ConcurrentDictionary(Of String, WebWorker)(StringComparer.InvariantCultureIgnoreCase) 

Private Sub ChangeState(ByVal ww As WebWorker, ByVal NewState As WorkerState) 

    If ListWebWorkers.ContainsKey(ww.Browser.Name) Then 
     ListWebWorkers.TryRemove(ww.Browser.Name) 
     ww.State = NewState 
     ListWebWorkers.TryAdd(ww.Browser.Name, ww) 
    End If 
End Sub 
1

您必須鎖定非線程安全的資源。這確保了在給定的時間只有一個線程正在訪問它們。

Private Sub ChangeState(ByVal ww As WebWorker, _ 
        ByVal NewState As WorkerState) 

    SyncLock ListWebWorkers 
     Dim oWBB As WebWorker = ListWebWorkers.Find(Function(item As WebWorker) item.Browser.Name.ToLower = ww.Browser.Name.ToLower) 
     If oWBB.Browser IsNot Nothing Then 
      ListWebWorkers.Remove(oWBB) 
      oWBB = ww 
      oWBB.State = NewState 
      ListWebWorkers.Add(oWBB) 
     End If 
    End SyncLock 
End Sub 
+0

該應用程序不是多線程的,但是使用多個webbrowser來完成一些工作。這是否適用於這裏 – Smith 2012-01-07 19:37:32

+0

如果該應用程序不是多線程的,那麼如何刪除一個項目兩次? – 2012-01-07 20:17:02