2010-02-11 12 views
6

Gibt es einen Sinn, das klassische Feld bool disposed auf einem anderen threadsafe-Typ zu verfolgen, um eine ObjectDisposedException am Anfang aller primär exponierten Methoden bedingt zu werfen?IDisposable, ObjectDisposedException und threadsafe-Typen

Ich habe dieses Muster an einigen Stellen online empfohlen, aber ich bin mir nicht sicher, ob die Autoren es richtig verwenden, so dass diese Frage davon ausgeht, dass sie es sind. In einem solchen Szenario scheint es so zu sein, dass die einzige Möglichkeit, sicherzustellen, dass die disposed Bedingung über die Bewertung der Bedingung hinaus wahr ist, einen Synchronisationsmechanismus wie lock() über den gesamten Körper jedes exponierten Elements einschließlich Dispose (bool) Methode. Würde das den Typ nicht effektiv wieder single-threaded machen?

Und wenn das stimmt, dann wäre es sinnlos, es zu benutzen, und deshalb können Sie sich nicht auf den ObjectDisposedException-Mechanismus in einigen IDisposable-Implementierungen verlassen - warum würden wir diesen Mechanismus dann immer einsetzen? t notwendig?

====

Ich denke, IDisposable und ObjectDisposedException einfach nicht zusammen für thread-safe-Typen gehen.

+0

Siehe auch: http://stackoverflow.com/questions/170028/how-would-you-simplfy-entering-and-exiting-a-readerwriterlock –

Antwort

4

Eine effizientere Möglichkeit, ein threadsicheres Objekt nicht zu entfernen, während eine Methode ausgeführt wird, ist die Verwendung einer ReaderWriterLockSlim. Lassen Sie alle öffentlichen Methoden während der Ausführung eine Lesesperre erhalten und geben Sie sie frei, wenn sie fertig sind. Habe Dispose eine Schreibsperre erhalten. Es wird warten, bis alle anderen Methoden abgeschlossen sind, bevor es seine Schreibsperre erhält. Es setzt dann isDisposed innerhalb der Schreibsperre, die es exklusiv hält. Alle Aufrufe an öffentliche Methoden nach Dispose erfolgt können isDisposed und werfen Sie die ObjectDisposedException.

ReaderWriterLockSlim

http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.aspx

+0

Coole Idee. Hast du eine Probe? Keine Dokumentation auf ReaderWriterSlimLock gefunden. Ist das etwas, das du schon mal gesehen hast oder etwas, das du gerade erst gemacht hast? –

+0

Nur Brainstorming, aber ich denke, es sollte gut für Ihre Anfrage funktionieren. Ich habe es in meiner ursprünglichen Antwort falsch geschrieben, es ist 'ReaderWriterLockSlim'. Ich habe einen Link zu MSDN-Dokumenten hinzugefügt. –

+0

Eigentlich funktioniert das fast, außer dass FXcop zu Recht darauf hinweist, dass ReaderWriterLockSlim IDisposable implementiert und zusammen mit den übrigen Ressourcen des Objekts entsorgt werden sollte. Wenn also einmal dispose aufgerufen wird, würde ich keine Lesesperre mehr bekommen, um zu testen, ob das Objekt entsorgt wurde oder nicht. –

3

Wenn das Verhalten des Objekts wird anders sein, wenn es bereits angeordnet ist, und wenn es wahrscheinlich ist, dass es verwendet wird, nachdem es angeordnet worden ist, dann müssen Sie halten Spur davon. Es ist besser, ObjectDisposedException zu werfen, als eine zufällige Ausnahme auszulösen, die auftritt, wenn das Objekt bereits entsorgt wurde und Sie es nicht zuerst prüfen.

+0

Ja, aber diese Frage bezieht sich darauf, wie eine ObjectDisposedException mit Sicherheit in einem Multithread-Szenario ausgelöst wird. –

+0

@Jason: In diesem Fall bearbeiten Sie Ihre Frage, um es zu sagen. –

0

Vorausgesetzt, dass der Boolean "Disposed" nur an einer Stelle aktualisiert wird, und es ist ein Fehler in Ihrem Aufrufer, das Objekt zu verwenden, nachdem sie Disposed aufgerufen hatten.

Ich denke, es ist gut genug, um ObjectDisposedException "die meiste Zeit" zu werfen, nachdem Dispose aufgerufen wurde. Ich sehe ObjectDisposedException als einen Debughelfer, nichts, was ein Anrufer abfangen sollte.

0

Wenn die Möglichkeit besteht, dass eine Methode aufgerufen wird, während ein Objekt entsorgt wird, sollte die Semantik der Methode so definiert werden, dass ein Aufruf auf einem entsorgten Objekt kein Problem darstellt. In Fällen, in denen es ein Problem geben könnte oder nicht, sollte man das "try/do" -Muster verwenden. Wenn Microsoft diesem Prinzip mit Control.BeginInvoke gefolgt wäre, gäbe es sowohl eine "Control.BeginInvoke" als auch eine "Control.TryBeginInvoke"; Letzteres würde explizit als Rückgabe false definiert und würde nichts tun, wenn ein Steuerelement vor dem Einreihen in die Warteschlange entfernt wurde (beachten Sie, dass Control.BeginInvoke mit true nicht garantieren würde, dass das Steuerelement nicht entfernt würde, bevor die Aktion tatsächlich ausgeführt wurde).Dieses Muster wäre beispielsweise in Szenarios für die Anzeigeaktualisierung sehr nützlich: Wenn ein Steuerelement nicht entfernt wird, möchte ich, dass seine Aktualisierungsroutine ausgeführt wird. Wenn es vor der Ausführung der Aktualisierungsroutine entsorgt wird, wird das Update jedoch ungültig und sein Fehlschlagen ist kaum ein Problem.

Verwandte Themen