Laden...

Es blitzt/flackert bei this.Dispose()

Erstellt von Pacher vor 2 Jahren Letzter Beitrag vor einem Jahr 1.038 Views
P
Pacher Themenstarter:in
18 Beiträge seit 2015
vor 2 Jahren
Es blitzt/flackert bei this.Dispose()

Hallo!
Es wird ja öfters empfohlen eine Winform mit this.Dispose() zu schließen, damit alles aufgeräumt wird.
Es blitzt/flackert jedoch kurz unangenehm, das bei this.Close() nicht auftritt.
Meine Frage daher..., gibt es eine Möglichkeit beides unter einem Hut zu bringen oder wird das Dispose eh überbewertet?
Es gibt ja auch noch:


using(Form f = new Form())
{
     f.Show();
}

Wird auch hier alles "aufgeräumt"?
Sorry, aber mit Speicherverwaltung hab ich mich noch nicht näher beschäftigt...

LG Pacher

16.828 Beiträge seit 2008
vor 2 Jahren

Ich hab das ehrlich gesagt noch nie gelesen, dass man direkt Dispose nutzen soll - denn Close ruft Dispose auf.
Macht irgendwie daher keinen Sinn.

Aber was Close auch macht ist, das Fenster sauber zu schließen (Win32 Call).
Erst danach ruft Close dann Dispose auf. Daher würde ich eher sagen, dass der direkte Dispose-Call der falsche Weg ist.

Steht auch alles in den Docs
Form.Close Methode (System.Windows.Forms)

PS: Dein using() ist nichts anderes als ein impliziter Dispose Call.
Ändert also nichts.
Mit Speicherverwaltung hat das nur Sekundär was zutun, viel mehr wie man Controls/Objekte in Forms/C# handhabt.
Und das sollte man bei der UI Programmierung schon wissen, gehört schon irgendwie zu den Grundlagen, weils da sonst schnell knallen kann 😉

P
Pacher Themenstarter:in
18 Beiträge seit 2015
vor 2 Jahren

Hallo @Abt!
Oh vielen Dank für die ausführliche Antwort...beruhigt mich ungemein, dass ich wieder auf this.Close zurückkehren kann!
Wo hab ich das Dispose her, naja es gibt auf YouTube unzählige "Lehr-Videos" wo es so gehandhabt oder vorgeschlagen wird!
Es hat wohl jeder seinen eigenen Programmierstil...!

Nochmals Danke für die schnelle Antwort!
LG Pacher

16.828 Beiträge seit 2008
vor 2 Jahren

Hat mit Stil wenig zutun: ist halt in diesem Anwendungsfall falsch.

2.079 Beiträge seit 2012
vor 2 Jahren

Wo hab ich das Dispose her, naja es gibt auf YouTube unzählige "Lehr-Videos" wo es so gehandhabt oder vorgeschlagen wird!

Diese "Lehr-Videos" sind leider in den meisten Fällen wirklich nicht gut.

Und gegen Dispose spricht nichts, im Gegenteil, das Prinzip ist richtig und wichtig.
Aber man sollte verstanden haben, was es ist bzw. wofür es da ist und das Schließen von Fenstern gehört nicht dazu.
Dispose soll - verrät ja schon der Name - aufräumen, alles das, was nicht automatisch (z.B. durch den GC) aufgeräumt werden kann, also nicht verwaltete Ressourcen.

Beim WinForms-Fenster gehört unter Anderem dazu, über die WinAPI das Fenster zu entsorgen. Das kann der GC nicht alleine, da er keine Kontrolle über Windows hat.
Man könnte aber z.B. auch ein Gerät wieder in einen sicheren Zustand zurück versetzen.
Oder man ruft Dispose aller anderen Objekte auf - zumindest solange die Klasse auch die Kontrolle darüber hat.

Das heißt natürlich nicht, dass irgendetwas kaputt geht, wenn man kein Dispose aufruft, zumindest bei .NET kann man davon ausgehen, dass irgendwann trotzdem aufgeräumt wird.
Die Dispose-Methode gibt allerdings Kontrolle darüber, wann und unter welchen Bedingungen das gemacht wird, deshalb sollte man es (fast) immer auch aufrufen.

Mehr dazu:
Implement a Dispose method

J
61 Beiträge seit 2020
vor 2 Jahren

Bei ShowDialog wird ein Schuh aus dem using.

Ein modaler Dialog hält die Abarbeitung im GUI-Thread auf, wird beim Schließen versteckt, dann verarbeitet man das Ergebnis und benötigt die Form danach nicht mehr.

16.828 Beiträge seit 2008
vor 2 Jahren

zumindest bei .NET kann man davon ausgehen, dass irgendwann trotzdem aufgeräumt wird.

.. was nur für .NET Runtime Objekte gilt; nicht für unmanaged / externe Windows Objekte.
Gerade im UI Bereich hat man aber oft Objekte, die man zwingend aufräumen muss.

2.079 Beiträge seit 2012
vor 2 Jahren

.. was nur für .NET Runtime Objekte gilt; nicht für unmanaged / externe Windows Objekte.
Gerade im UI Bereich hat man aber oft Objekte, die man zwingend aufräumen muss.

Ich meine, dass die alle mit dem "vollständigen" Disposable-Pattern implementiert sind - sofern notwendig.
Also dass, wenn Dispose nicht aufgerufen wurde, es der GC am Ende tut, wie hier beschrieben.

Oder gibt's auch Klassen, die das nicht so machen?

16.828 Beiträge seit 2008
vor 2 Jahren

Wenn Du beispielsweise mit OS/File/....-Handles arbeitest oder auch ganz banal mit Bitmaps bist Du i.d.R. selbst für das Freigeben verantwortlich.

2.079 Beiträge seit 2012
vor 2 Jahren

Das implementiert dann aber kein IDisposable.

Mir ging es darum, dass alles was IDisposable implementiert, auch disposed wird - entweder mit Kontrolle im eigenen Code oder ohne Kontrolle im Destruktor.
Setzt natürlich voraus, dass alle Klassen, die unmanaged Ressourcen verwalten, im Destruktor auch aufräumen, mir ist aber keine bekannt, die das nicht tut.
Und für z.B. FileHandles gibt's ja die SaveFileHandle-Klasse (bzw. SaveHandle), die im Destruktor freigibt, was nötig ist und auch IDisposable implementiert.

Aber klar, wenn man sich "selber" unmanaged Ressourcen besorgt, muss man sie auch selber wieder freigeben.

16.828 Beiträge seit 2008
vor 2 Jahren

Klar, ein Image (und damit Bitmap) implementiert IDisposable und trotzdem bist (in den meisten Fällen) selbst in der Pflicht.
IDisposable garantiert kein korrektes Aufräumen. Das ist ein Irrtum.

Mir ging es darum, dass alles was IDisposable implementiert, auch disposed wird

Nein. Der GC kennt kein IDisposable, sondern nur Finalize (was Du mit Dekonstruktor meinst).
Man muss also selbst alles korrekt implementieren, dass das funktioniert.

IDisposable ist ein Pattern, keine Implementierung.

2.079 Beiträge seit 2012
vor 2 Jahren

Man muss also selbst alles korrekt implementieren, dass das funktioniert.

Wovon ich bei .NET-Klassen ausgehen würde - mir geht es nur um .NET-Klassen.
Bei allem, was man selber implementiert, muss man das natürlich auch selber sicherstellen.

5.658 Beiträge seit 2006
vor 2 Jahren

Ich glaube, ihr redet aneinander vorbei 🙂

@Palladin007
Ja, wenn eine Klasse IDisposable implementiert, dann muß man selbst dafür sorgen, daß am Ende Dispose aufgerufen wird. Entweder durch den Aufruf der Methode oder durch die Verwendung des using-Statements.

Weeks of programming can save you hours of planning

2.079 Beiträge seit 2012
vor 2 Jahren

Ich glaube, ihr redet aneinander vorbei

Ja, ich glaube auch 😁

Für mich klang es zwischendurch so, als könne der Eindruck entstehen, es sei gefährlich, Dispose nicht aufzurufen. Diese Angst wollte ich nehmen.
Bei .NET sind alle Klassen so implementiert, dass - auch wenn man vergisst, Dispose aufzurufen - irgendwann automatisch alles Nötige aufgeräumt wird.
Man verliert zwar die Kontrolle darüber, wann aufgeräumt wird und man riskiert Probleme im eigenen Programm, aber es wird spätestens nach dem Beenden des Programms alles aufgeräumt sein.

Wenn man z.B. einen FileStream öffnet und den nicht richtig disposed, riskiert man zwar Fehler, aber die Datei bleibt nicht auf ewig im Windows gesperrt, nur weil man das Dispose (bei Streams geht auch Close) vergessen hat.
Für Code, der nicht von Microsoft stammt, kann man das natürlich nicht sagen, aber die meisten großen/bekannten Frameworks sind nicht weniger professionell entwickelt.

Man sollte natürlich trotzdem immer darauf achten (bis auf die sehr wenigen Ausnahmen), das erspart merkwürdige Fehler und bietet mehr Kontrolle.

16.828 Beiträge seit 2008
vor 2 Jahren

Ja, ich glaube auch 😁

Ich nicht, denn:

Wenn man z.B. einen FileStream öffnet und den nicht richtig disposed, riskiert man zwar Fehler, aber die Datei bleibt nicht auf ewig im Windows gesperrt, nur weil man das Dispose (bei Streams geht auch Close) vergessen hat.

Und genau das stimmt nicht, denn genau das Gegenteil ist der Fall - wie oben schon geschrieben. Es gibt keine Garantie, dass der GC in diesem Fall Objekt wegräumt und damit zB das Handle freigibt. Das ist ein Irrtum. Immer noch.
Wenn ein managed Objekt nicht mehr referenziert wird, dann würde der GC das Objekt wegräumen; hat das Objekt aber noch "rooted references", zB. in Form eines unmanaged Handles, dann wird der GC das Objekt nicht aufräumen. Es wird kein Finalizer aufgerufen, damit kein Dispose (nach Pattern) gecallt. Egal wie gut Du Disposable implementiert hast.
Damit hast Du eine Objektleiche und zB die Datei bleibt gesperrt.

Die Datei wird erst dann entsperrt, wenn der Prozess beendet und damit auch die rooted reference wegfällt.

2.079 Beiträge seit 2012
vor 2 Jahren

Die Datei wird erst dann entsperrt, wenn der Prozess beendet und damit auch die rooted reference wegfällt.

Das habe ich doch geschrieben?

Siehe:

Man verliert zwar die Kontrolle darüber, wann aufgeräumt wird und man riskiert Probleme im eigenen Programm, aber es wird spätestens nach dem Beenden des Programms alles aufgeräumt sein.

Was hier vielleicht noch fehlt:
Man riskiert natürlich auch Probleme in anderen Programmen, wenn die auf die gleiche Ressource zugreifen, solange der eigene Prozess noch läuft, aber die werden vermutlich (hoffentlich) damit umgehen können. Und diese Probleme sind - wie schon geschrieben - spätestens nach dem Beenden des eigenen Programms wieder beseitigt.

Ich beziehe mich auf den Blick von außen:
Gefährdung für die Hardware, dauerhaft gesperrte Datei-Leichen oder andere Probleme, nur weil man ein bisschen herum experimentiert und dabei nicht aufgepasst hat.

V
1 Beiträge seit 2022
vor einem Jahr

Ein modaler Dialog hält die Abarbeitung im GUI-Thread auf, wird beim Schließen versteckt, dann verarbeitet man das Ergebnis und benötigt die Form danach nicht mehr.

3.825 Beiträge seit 2006
vor einem Jahr

Wenn man das .Dispose() weglässt bleiben Fragmente vom WinForms im Speicher und irgendwann ist der Speicher dann voll.

Ist bei meinen Kunden mehrfach passiert nach mehreren Tausend Fenstern öffnen und schließen. ich weiß aber nicht was die Kunden gemacht haben.

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3

2.079 Beiträge seit 2012
vor einem Jahr

Die Implementierung von Close:
https://source.dot.net/#System.Windows.Forms/System/Windows/Forms/Form.cs,b6605a5b113b45f7

Dem Code nach wird auch nicht immer Dispose beim Close aufgerufen.
Wenn ich das richtig interpretiere, müsste doch immer ein Handle existieren, sobald die Form angezeigt wurde, entsprechend wird nie Dispose aufgerufen.

Wenn ich der Message folge:
https://source.dot.net/#System.Windows.Forms/System/Windows/Forms/Form.cs,835f7070c7e52263

Dann wird hier auch nicht immer Dispose aufgerufen.
Ich denke daher, dass es schon sinnvoll ist, die Form zu disposen, allerdings erst nachdem sie geschlossen wurde.