2010-11-29 12 views
1

Ich versuche ein Objekt zu sperren, das durch seine Elemente iteriert. Die Arraylist allThreads von mir ist wirklich nicht gesperrt, weil während der Ausführung der "foreach" bekomme ich eine Ausnahme, die besagt: "Sammlung wurde geändert; Aufzählungsoperation kann nicht ausgeführt werden." Ich dachte, das war die ganze Sache mit Schloss?Lock() nicht effektiv

lock (mApp.allThreads) 
{ 
    foreach (Thread t in mApp.allThreads) 
     if (t.Name == "OpcDAWriter" && t != Thread.CurrentThread) 
      t.Join(); 
} 
+0

Wo ist der Code, der allThreads ändert? Sperrt es auch die Sammlung? –

Antwort

0

Sie treten in den t Faden, so es wird geschieht wahrscheinlich entfernt von mApp.allThreads oder etwas anderes wegen der Verbindung, so dass die Sammlung ändern.

Auch, weil Sie das Objekt suchen, nicht alle anderen Methoden können auf es sperren, funktioniert das Schloss nur, wenn alle Methoden Zugriff auf das Objekt auf es sperren. Sie könnten versuchen, ein externes Objekt als Ihren Sperrparameter zu verwenden, dh:

aber ich bezweifle, dass das irgendetwas ändern wird.

3

Ich denke, Sie haben möglicherweise missverstanden, was lock für Sie tut. Es nicht verhindern anderen Code aus dem Objekt manipulieren, dass Sie eine Sperre ausgeführt haben. Es verhindert, dass ein Thread ein Long in einem Objekt erhält, während ein anderer Thread das Lock hält.

Wenn Sie verhindern möchten, dass ein Thread die Sammlung manipuliert, während ein anderer Thread darüber iteriert, müssen Sie sowohl den Iterationscode als auch den Manipulationscode in lock Blöcke setzen und dasselbe Objekt sperren.

Einfaches Beispiel:

class LockDemo 
{ 
    private IList<string> _items; 
    private object _lock = new object(); 
    public LockDemo() 
    { 
     _items = new List<string>(new[] { "one", "two", "three" }); 
    } 

    public void RemoveItem(string item) 
    { 
     lock (_lock) 
     { 
      _items.Remove(item); 
     } 
    } 

    public void DoSomethingThatIteratesOverTheList() 
    { 
     lock (_lock) 
     { 
      foreach (var item in _items) 
      { 
       // do something with item 
      } 
     } 
    } 
} 

Beachten Sie, wie alle Zugriff auf die Liste (mit Ausnahme des Konstruktor in diesem Fall) in lock Blöcken gewickelt ist, die alle Sperren auf demselben Objekt ist. Beachten Sie auch, dass dieses Objekt nicht die Liste selbst ist, sondern ein Objekt, das nur zum Sperren verwendet wird. Dies zeigt, dass lock das Objekt nicht als solches sperrt, sondern einen Mechanismus bereitstellt, um zu steuern, welche Teile des Codes von verschiedenen Threads parallel ausgeführt werden können oder nicht.

+0

Ahh jetzt verstehe ich das Verhalten von Schloss. (Hatte nur Sperren mit einem von zwei Benutzern meines _lock-Objekts verwendet). Tolle Erklärung, danke Jungs! – AKZ