2013-04-07 19 views
8

Sprich, wenn ich den folgenden Block auf C# -Code haben:Ausnahmen innerhalb des Schlossblock

public class SynchedClass 
{ 
    public void addData(object v) 
    { 
     lock(lockObject) 
     { 
      //Shall I worry about catching an exception here? 

      //Do the work 
      //arr.Add(v); 
     } 
    } 
    private List<object> arr = new List<object>(); 
    private object lockObject = new object(); 
} 

Soll ich versuchen, Ausnahmen innerhalb des lock Block zu fangen? (Meine Hauptsorge ist, dass die Ausnahme innerhalb des Schlosses ausgelöst werden kann, wodurch verhindert wird, dass das Schloss "entsperrt" wird.)

Antwort

20

Die Sperre wird aufgehoben, wenn die Ausnahme vom Sperrblock entfernt wird.

, dass, weil lock(){...} ist, wird durch Compiler übersetzt sich grob in:

Monitor.Enter(obj); 
try{ 

// contents of the lock block 

}finally{ 
    Monitor.Exit(obj); 
} 
+0

Also die Art, wie ich es oben geschrieben habe, sollte gut sein, oder? – c00000fd

+1

Wenn Sie die Ausnahme irgendwo im Call-Stack fangen, sollte es in Ordnung sein. Sonst stürzt deine App einfach ab :) – alex

1

Eine Verriegelungs Anweisung der Form "lock (x), ...", wobei x ein Ausdruck eines Referenz-Typ ist, ist genau äquivalent zu (C# 4.0):

1

Es gibt mehr zu betrachten als nur die Freigabe des Mutex.

Eine Ausnahme, die mit lock auftritt, wird die Sperre freigeben, aber in welchem ​​Zustand befindet sich das Programm jetzt? Ein Thread, der auf die Sperre wartet, wird jetzt aufwachen und wird sich vielleicht jetzt mit einem ungültigen Zustand befassen. Dies ist ein schwieriges Problem ohne ideale Lösung.

Das Beste ist, versuchen Sie, Ihre Sperren so klein wie möglich zu halten und Methoden aufzurufen, die nicht werfen. (Das Ignorieren der elepant in dem Raum, der das Böse ist

Für eine gute Diskussion dieser Probleme, siehe Eric Lippert's Artikel: Locks and exceptions do not mix.

+0

Ja, es ist leichter gesagt als getan. Ich glaube nicht, dass es eine einzelne .NET-Methode gibt, die keine Ausnahme auslöst. – c00000fd