50 Stimmen

Gibt es eine Möglichkeit zu erkennen, ob ein Objekt gesperrt ist?

Gibt es eine Möglichkeit zu bestimmen, ob ein Objekt in C# gesperrt ist? Ich habe die wenig beneidenswerte Position, durch Design, wo ich von einer Warteschlange innerhalb einer Klasse zu lesen, und ich muss den Inhalt in eine Sammlung in der Klasse zu dumpen. Aber diese Sammlung ist auch lesen/schreiben von einer Schnittstelle außerhalb der Klasse. Es kann also durchaus vorkommen, dass in die Sammlung geschrieben wird, während ich gleichzeitig in sie schreiben möchte.

Ich könnte es umprogrammieren, z. B. mit Delegaten, aber das wäre hässlich.

45voto

casperOne Punkte 72238

Sie können jederzeit die statische TryEnter Methode über die Monitor Klasse mit einem Wert von 0 für den zu wartenden Wert. Wenn er gesperrt ist, gibt der Aufruf false zurück.

Das Problem dabei ist jedoch, dass Sie sich vergewissern müssen, dass die Liste, auf die Sie den Zugriff synchronisieren wollen, für sich selbst gesperrt ist, damit der Zugriff synchronisiert werden kann.

Es ist im Allgemeinen eine schlechte Praxis, das Objekt, auf das der Zugriff synchronisiert wird, als das zu sperrende Objekt zu verwenden (es werden zu viele interne Details eines Objekts preisgegeben).

Denken Sie daran, dass sich die Sperre auch auf etwas anderes beziehen kann, so dass es sinnlos ist, sie nur auf der Liste aufzurufen, wenn Sie nicht sicher sind, dass es sich um die Liste handelt, die gesperrt werden soll.

11voto

Barry Kelly Punkte 40566

Monitor.TryEnter ist erfolgreich, wenn das Objekt nicht gesperrt ist, und gibt false zurück, wenn das Objekt in diesem Moment gesperrt ist. Beachten Sie jedoch, dass es hier ein implizites Wettrennen gibt: In dem Moment, in dem diese Methode zurückkehrt, darf das Objekt nicht mehr gesperrt sein.

9voto

Ich bin nicht sicher, ob ein statischer Aufruf von TryEnter mit einer Zeit von 0 garantiert, dass die Sperre nicht erworben wird, wenn sie verfügbar ist. Die Lösung, die ich tat, um im Debug-Modus zu testen, dass die Sync-Variable gesperrt wurde, war die folgende:

#if DEBUG
// Make sure we're inside a lock of the SyncRoot by trying to lock it.
// If we're able to lock it, that means that it wasn't locked in the first
// place.  Afterwards, we release the lock if we had obtained it.
bool acquired = false;
try
{
    acquired = Monitor.TryEnter(SyncRoot);
}
finally
{
    if (acquired)
    {
        Monitor.Exit(SyncRoot);
    }
}
Debug.Assert(acquired == false, "The SyncRoot is not locked.");
#endif

6voto

Aliaksei Kliuchnikau Punkte 13329

Derzeit können Sie Monitor.TryEnter aufrufen, um zu prüfen, ob das Objekt gesperrt ist oder nicht.

In .NET 4.0 wird das CLR-Team die "Lock inspection API" hinzufügen.

Hier ist ein Zitat aus Rick Byers Artikel:

Schlossinspektion
Wir fügen ICorDebug einige einfache APIs hinzu, die es Ihnen ermöglichen, verwaltete Sperren (Monitors) zu untersuchen. Wenn zum Beispiel ein Thread blockiert ist und auf eine Sperre wartet, können Sie herausfinden, welcher andere Thread die Sperre gerade hält (und ob es ein Timeout gibt).

Mit dieser API können Sie also prüfen:
1) Welches Objekt hält eine Sperre?
2) Wer wartet auf sie?

Ich hoffe, das hilft.

6voto

user626528 Punkte 13339

Monitor.IstEingetragen

Ermittelt, ob der aktuelle Thread die Sperre für das angegebene Objekt hält.
Verfügbar seit 4.5

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X