IsDisposed assertions
-
Vielleicht hilft Dir die SOS.dll weiter.
http://msdn.microsoft.com/en-us/library/bb190764(VS.80).aspxHier gibts noch ein MSDN Magazin Artikel:
http://msdn.microsoft.com/en-us/magazine/cc164138.aspxSimon
Edit:
Vielleicht reichen Dir die Informationen, die mit Perfmon.exe rauszukriegen sind. Bei Performance Object ".NET Memory" gibts einige interessante Counters.
-
Hallo
hustbaer schrieb:
(einfaches Beispiel: Form.Show -> Dispose automatisch, Form.ShowDialog -> Dispose muss manuell aufgerufen werden) denke ich mir muss es doch da einige nette Debugging-Tools geben.
Echt? Das wusste ich noch nicht.
chrische
-
Ein Memory-Profiler bietet das normalerweise an, das .Net Framework stellt also derartige Mechanismen schon bereit. Ich würde aber tatsächlich lieber nen fertigen Profiler verwenden und nicht von Hand was dafür coden.
EDIT: Genaugenommen gehen die Profiler auf die Finalizer-Queue los, aber eine korrekt geschrieben Dispose() Methode entfernt die Objekte eben aus dieser Queue. Also du musst nach finalized Objekten schauen.
-
Huch, hab ganz übersehen dass hier Antworten drin sind
Danke für die Hinweise.
Was Performance-Counter angeht: Counter alleine sind ja nicht besonders aussagekräftig. Man weiss dann zwar wieviel "schief geht", aber nicht genau wo.
Kennt jemand einen guten Profiler/Memory-Profiler für .NET? Gratis bzw. billig?
-
chrische5 schrieb:
Hallo
hustbaer schrieb:
(einfaches Beispiel: Form.Show -> Dispose automatisch, Form.ShowDialog -> Dispose muss manuell aufgerufen werden) denke ich mir muss es doch da einige nette Debugging-Tools geben.
Echt? Das wusste ich noch nicht.
chrische
Jo, echt
Der Sinn dahinter ist denke ich folgender:private void Foo() { using (SettingsDialog sd = new SettingsDialog(this.settingA, this.settingB)) { sd.ShowDialog(this); // wenn hier automatisch b.Dispose gemacht würde this.settingA = sd.GetSettingA(); // hätten wir hier this.settingB = sd.GetSettingB(); // und hier ein Problem, da wir auf einen Zombie zugreifen müssten } }
Natürlich könnte man (oft, aber nicht immer) "GetSettingA" und "GetSettingB" so implementieren dass sie auch auf einem Zombie (=Objekt auf das bereits Dispose aufgerufen wurde) noch funktionieren, aber es ist einfach nicht sauber. Sauber wäre wenn "GetSettingA" und "GetSettingB" in dem Fall eine ObjectDisposedException werfen, und damit würde der Code oben nichtmehr funktionieren wenn ShowDialog die Form selbst disposen würde. Und eben, in manchen Fällen ginge das nichtmal gescheit - z.B. wenn man nach ShowDialog noch auf irgendwelche Dinge in der Form zugreifen muss welche selbst disposable sind.
Bei Form.Show wäre es dagegen ganz schrecklich doof wenn man Dispose selbst aufrufen müsste - dann müsste man immer tracken welche Forms man anzeigt, bzw. in jeder Form das "this.Dispose" in OnClose (oder wie die Funktion heisst) selbst aufrufen. Was beides IMO ziemlich grausam wäre.
Von daher eigentlich "logisch" dass es sich so und nicht anders verhält, aber man kann schnell drüberstolpern wenn man es nicht weiss bzw. einfach nicht drüber nachgedacht hat.
-
@hustbaer
Was konntest Du jetzt unternehmen, um die Dispose Aufrufe zu verfolgen?Simon
-
Hallo
Wenn ich also ohne using arbeite und ShowDialog aufrufe, muss ich noch sd.Dispose() aufrufen?
chrische
-
chrische5 schrieb:
Hallo
Wenn ich also ohne using arbeite und ShowDialog aufrufe, muss ich noch sd.Dispose() aufrufen?
chrische
Ja.
-
theta schrieb:
@hustbaer
Was konntest Du jetzt unternehmen, um die Dispose Aufrufe zu verfolgen?Simon
Noch nix
Im Moment ist das nicht das Dringendste, deswegen hab' ich da (noch) nicht viel Zeit investiert. Ich wollte hauptsächlich vorab fragen ob jmd. da gute Tools kennt. Dachte mir dass viele Leute da was gutes Kennen - wohl falsch gedachtWas mir heute noch eingefallen ist...:
In .NET gibt's ja einiges an Reflection, und dynamisch Code generieren kann man ja auch. Leider hab' ich mich mit diesen Dingen noch nicht soweit auseinandergesetzt dass ich weiss was geht und was nicht. Daher die Frage: Könnte ein Programm (z.B. so ein "Memory-Profiler") hergehen und sich alle Stellen in einem Programm raussuchen wo ein ctor einer Klasse aufgerufen wird die von IDisposable erbt, und dann dort dynamisch Code einfügen der für jedes Objekt mitschreibt wo (Stacktrace) der Aufruf stattgefunden hat der das Objekt initialisiert hat? Bzw. den entsprechenden Code gleich in den ctor einfügen? Das wäre dann so ziemlich das Beste was ich mir diesbezüglich vorstellen kann - dann könnte man zu den finalisierten Objekten auch immer gleich sehen wo diese angelegt wurden.
Im Prinzip ähnlich zu dem was der gute alte Bounds-Checker macht wenn man den generierten Code von Bounds-Checker vor einem Testlauf verwursten lässt.
Interessieren würde mich a) ob das grundsätzlich möglich ist und b) ob jemand eine fertige Implementierung kennt.
-
.Dispose() nervt unheimlich - Ich frag mich ob das nich irgendwie möglich gewesen wäre das es auch ohne klappt