Wie behandelt man die von Dispose geworfene Ausnahme?
Kürzlich, ich wurde untersucht, einige knifflige bugs über das Objekt nicht entsorgt.
Fand ich einige Muster im code. Es wird berichtet, dass einige m_foo nicht entsorgt, während es scheint, alle Instanzen von SomeClass entsorgt wurde.
public class SomeClass: IDisposable
{
void Dispose()
{
if (m_foo != null)
{
m_foo.Dispose();
}
if (m_bar != null)
{
m_bar.Dispose();
}
}
private Foo m_foo;
private Bar m_bar;
}
Ich den Verdacht, dass Foo.Entsorgen Sie könnten werfen eine Ausnahme, so dass der folgende code nicht ausgeführt, so m_bar nicht entsorgt.
Da Foo/Bar kann von einem Dritten, so ist es nicht gewährleistet, dass Sie nicht werfen Ausnahme.
Wenn nur wickeln Sie alle Entsorgen Aufruf mit try-catch, der code wird wiederum zu plump.
Was ist best practice, um diese zu bewältigen?
InformationsquelleAutor der Frage Morgan Cheng | 2009-06-23
Du musst angemeldet sein, um einen Kommentar abzugeben.
Seine wahre, dass es sein kann ziemlich schlecht Auslaufen eine Ausnahme von Ihrer dispose-Methode, zumal die Sachen, die IDisposable implementiert, wird in der Regel geben Sie einen finalizer, rufen Sie Dispose auf.
Das problem ist, kehren das problem unter den Teppich durch Behandlung einer Ausnahme kann verlassen Sie mit einigen sehr schwer zu Debuggen Situationen. Was ist, wenn Ihr IDisposable zugewiesen einen kritischen Abschnitt der Sorten, die erst veröffentlicht wird, nachdem entsorgen. Wenn Sie die Tatsache ignorieren, dass die Ausnahme passiert ist, Sie bis Ende Mai in der deadlock-zentrale. Ich denke, dass Ausfälle in Verfügen sollte einer der Fälle, wo Sie wollen, um frühzeitig ausfällt, so kann man den Fehler beheben, sobald Ihr entdeckt.
Natürlich ist es hängt alles davon ab, das Objekt entsorgt werden, für einige Objekte, die Sie möglicherweise in der Lage, sich zu erholen, andere nicht. Als Allgemeine Faustregel gilt, Entsorgen, sollten Sie nicht throw Ausnahmen, wenn verwendet, richtig, und Sie sollten nicht haben, um code defensiv um Ausnahmen in verschachtelten Dispose-Methoden, die Sie anrufen.
Tun Sie wirklich nicht wollen, zu fegen, einen OutOfMemoryException-unter den Teppich?
Wenn ich hatte einen fragwürdigen 3rd-party-Komponente, die beliebig warf Ausnahmen Entsorgen würde ich es behoben UND host in einem separaten Prozess, ich könnte reißen, wenn er zu spielen begann.
InformationsquelleAutor der Antwort Sam Saffron
Wenn Dispose() wird aufgerufen, in der eine Fertigstellung Kontext und wirft eine Ausnahme, die Ihr Prozess wird beendet.
Wenn Sie vermuten, dass Foo.Dispose() wirft eine Ausnahme, würde ich Sie entsorgen es im letzten, wenn möglich, und wickeln Sie es in ein try/catch. Alles, was Sie tun können, um loszuwerden, es in den Fang - setzt den Verweis auf null. Es ist sehr schlecht zu werfen Ausnahmen von Dispose() und sollte vermieden werden.
Leider, wenn diese fehlerhaft ist, code von Drittanbietern, Ihre beste Wette wäre, um Sie zu bekommen, um es zu beheben. Sie sollten nicht manuell zu reinigen, nachdem Sie.
Hoffe, das hilft.
InformationsquelleAutor der Antwort womp
Weil Sie nicht haben, um die Allokation der Variablen in ein using () - Anweisung - warum nicht 'gestapelt' using-Anweisungen für diese?
Den 'gestapelten' using-Anweisungen werden wie folgt erweitert:
Also die Dispose () - Aufrufe werden in separaten finally-blocks:
Ich hatte eine harte Zeit der Suche nach einem Bezug für diese an einem Ort. Der 'stacked' using-Anweisungen gefunden werden, in einer old Joe Duffy blog-post (siehe Abschnitt "C# - und VB-Anweisung Verwenden, C++ - Stack-Semantik'). Die Joe Duffy post verwiesen wird, die von vielen StackOverflow Antworten auf IDisposable. Ich fand auch einen letzten Frage wo gestapelt using-Anweisungen für lokale Variablen angezeigt werden. Ich konnte nicht finden, dass die Verkettung von finally-Blöcken überall, aber der Sprache C# spec (Abschnitt 8.13 in C# 3.0-spec), und nur für mehrere varaibles innerhalb eines einzelnen 'mit' block, der nicht genau das, was ich Vorschlage, aber wenn Sie könnte die IL finden Sie die try/finally-Blöcke Ineinander verschachtelt sind. Auf der null-check, auch aus der C# - spec: 'Wenn ein null-Ressource erworben wird, dann wird kein Aufruf von Dispose ist gemacht, und es wird keine exception geworfen.'
InformationsquelleAutor der Antwort yzorg
Entsorgen soll nicht werfen Ausnahmen. Wenn es macht—es ist nicht gut geschrieben, so...
sollte genug sein.
InformationsquelleAutor der Antwort LukeSw
Laut Design-Regeln :
Also, wenn dein Programm abstürzt, weil der nicht behandelte Ausnahme von Dispose() - siehe Offizielle Lösung
InformationsquelleAutor der Antwort noonex
Nicht zu wiederholen-code für die Entsorgung von Objekten, schrieb ich die folgende statische Methode.
Der wichtigste Punkt ist, dass man es machen kann, eine Funktion, so dass Sie geben Sie nur eine Zeile pro Objekt Sie entsorgen möchten, halten Sie die Dispose-Methoden schön und sauber. In unserem Fall war es Konvention auf null entsorgt Zeiger, damit die ref-Parameter.
In Ihrem Fall, die Sie vielleicht hinzufügen möchten, exception-handling, oder machen Sie einen anderen Geschmack mit exception handling. Ich würde sicherstellen, dass Sie log/Haltepunkt Wann immer ein Dispose() throws Ausnahmen, aber wenn Sie können nicht verhindern, dass die nächste beste Sache ist, um sicherzustellen, dass das problem nicht ausbreiten.
InformationsquelleAutor der Antwort
In meinem Fall war es wegen einem thread den Zugriff auf UI-Elemente beim schließen der form. Ich resovled es durch den Abbruch der thread auf die form schließen. ("FormClosing" - event)
InformationsquelleAutor der Antwort Reza Taibur