Sauberes Beenden eines Programms

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 21 Antworten in diesem Thema. Der letzte Beitrag () ist von nafets.

    Sauberes Beenden eines Programms

    Hallo Community

    Auch wenn das ein Evergreen ist: Wenn man googelt (auch auf VB-Paradise), wie man sauber eine eigene VB.NET-Anwendung beenden soll, erhält man eine verwirrende Anzahl von Vorschlägen:

    VB.NET-Quellcode

    1. Me.Close
    2. Me.Finalize
    3. Me.Dispose
    4. Application.Exit
    5. Application.Close
    6. Environment.Exit(0)
    7. gar nichts nötig, klicken auf [x] reicht
    8. usw.

    Einig ist man sich praktisch nur darin, dass End und alle Kill schlechte Lösungen sind, da der Prozess abgewürgt wird ohne Aufräumarbeiten. Was ist nun aber von all den anderen Vorschlägen der Beste? Welche sind äquivalent? Funktionieren tun wohl alle Vorschläge "irgend wie". Aber wer sieht hier klar?

    Vielen Dank für jede "Aufklärung".

    Bernhard
    mit Me. sprichst du nur das aktuelle Objekt an. Anders gesagt, besteht dein gesamtes Projekt aus nur einer Form, schließt du damit nicht das Programm, sondern lediglich die Form. Nur als "Nebeneffekt" schließt sich dabei das Programm mit. hast du jedoch mehrere Forms, wo auch mehrere Offen sind, schließt du nur diejenige, die das Me.Close oder sonst was hat.

    Application.Close lässt sich unter C# nicht finden, ich vermute es ist daher einer der "Bösen Funktionen"?

    Edit: Environment.Exit ist die absolute Vorschlaghammer Methode, es wird alles sofort beendet, und kann, so MSDN nicht angehalten werden.
    Application.Exit() lässt noch sämtliche Messageloops sich abarbeiten und kann z.B. im FormClosing() Event noch gestoppt werden.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „EaranMaleasi“ ()

    Also wenn du nur eine Form hast, "reicht" Me.Close(). Bei mehreren Form müssen, je nach Konfiguration des Anwendungsframeworks, alle oder die Startform geschlossen werden.
    Wenn du nicht verwaltete Objekte nutzt, was WinForms macht, bleiben mit Environment.Exit "Leichen" (Memoryleaks) im Arbeitsspeicher zurück. Diese Verschwinden nach einem Neustart.

    Bei Konsolenanwendungen gibt es keine Form zum Schließen, sondern da muss die Main-Methode verlassen werden.
    Mit freundlichen Grüßen,
    Thunderbolt

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Thunderbolt“ ()

    Hi

    VB.NET-Quellcode

    1. Me.Close 'Schließt das aktuelle Fenster. Wenn die Anwendung an dieses gebunden ist (d.h. Application.Run(deineForm) wird ausgeführt, wird die Anwendung im Normalfall beendet (faktisch besteht die Anwendung solange, wie mindestens ein Thread aktiv ist)
    2. Me.Finalize 'Wird aufgerufen, wenn eine Instanz von der Garbage Collection freigegeben wird
    3. Me.Dispose 'Existiert im Normalfall für Typen, die die IDisposable-Schnittstelle implementieren
    4. Application.Exit 'Beendet die Nachrichtenschleife (afaik des aktuellen Threads) und schließt damit alle Fenster in diesem.
    5. Application.Close 'Kenne ich nicht, ist aber, falls existent, definitiv nicht sinnvoll
    6. Environment.Exit(0)'Absolut nicht zu empfehlen. Dadurch "tötest" du die Anwendung, ohne, dass sie irgendwelche benötigten Maßnahmen einleiten kann
    7. System.Diagnostics.Process.GetCurrentProcess().Kill() 'selbiges wie bei Environment.Exit(0)


    Es kommt ganz darauf an, wie deine Anwendung konstruiert ist. Wenn sie nur ein Hauptfenster hat, das irgendwann geschlossen wird, genügt Me.Close völlig. Wenn sie aber komplexer gestaltet ist und Threads benutzt, muss jeder dieser Threads sich irgendwann selbst beenden (ja, sich selbst, System.Threading.Thread.Abort ist keine Option, allerhöchstens bei Fehlerkorrektur und selbst dann nur mit genügend Hintergrundwissen darüber, was alles passieren kann). Sowas ist nötig, denn sonst hinterlässt man die Anwendung in einem möglicherweise "instabilen" Zustand. Stell' dir vor, es müssten Daten gespeichert werden oder es werden Daten übertragen. Die Anwendung schießt sich selbst ab, ohne, dass die Übertragung abgeschlossen wird (kann dir bei Me.Close und Application.Exit afaik nicht passieren). Das passiert möglicherweise, wenn Process.Kill oder Environment.Exit aufgerufen werden.
    Die Anwendung läuft normalerweise bei einem Einstiegspunkt an. Dort steht dann bspw. Das Application.Run(new MainForm()) ab (in VB.Net standardmäßig bei Windows Forms Anwendungen im Anwendungsframework). Dies ist quasi der Ursprung der Anwendung, dort wird all das ausgeführt, was danach passieren wird, so auch eben das Anzeigen des Hauptfensters, usw. Das Programm sollte sich dann beenden, wenn dieser "Hauptstrang" zuende ist. D.h. alle benötigten Vorgänge sollen dort abgeschlossen sein und alle Threads und sonstige parallele Vorgänge sollen sich dort beendet haben.

    @Thunderbolt : Vorsicht, Environment.Exit und Application.Exit sind zwei verschiedene Dinge.

    Viele Grüße
    ~blaze~
    @tolio : Siehe blazes (hmm) Antwort. Application.Exit ist imho das angebrachteste für komplexere Anwendungen, es lässt die Nachrichtenschleife einfach auslaufen. Environment.Exit ist wie erwähnt ein Vorschlaghammer, der einfach die Anwendung tot schlägt. Thunderbolt hat diese verwechselt.
    »There's no need to "teach" atheism. It's the natural result of education without indoctrination.« — Ricky Gervais
    Das sehe ich gleich, einzige Ausnahme war bei mir im MenuStrip das Item "Exit", wobei ich bis heute nicht weiß warum einige Appl. das haben (vorausgesetzt der X-Button wurde nicht umfunktioniert)
    »There's no need to "teach" atheism. It's the natural result of education without indoctrination.« — Ricky Gervais
    Anwendungen, die eine eigene Nachrichtenschleife benutzen, wie bspw. bei Anwendungen, die aus einem NotifyIcon bestehen, das ein Fenster anzeigt, besitzen eine Nachrichtenschleife und werden im Allgemeinen nicht über das Hauptfenster gestartet und beendet. Fenster, die sich mehrerer aufeinanderfolgender Fenster bedienen, besitzen solch eine Möglichkeit ebenfalls nicht.

    Viele Grüße
    ~blaze~
    Normalerweise sollte ein OS den Speicher beim Beenden freigeben, aber da sollte man sich nicht drauf verlassen. Ich hatte da mal einen Artikel zu, finde ihn aber gerade nicht.
    Mit freundlichen Grüßen,
    Thunderbolt
    Ich würde mal damit rechnen, dass die Speicherseiten des Programms selbst freigegeben werden. Wenn nun ein Programm beendet wird, das bspw. Speicher von anderen Programmen anfordert und dieser nicht freigegeben wird, kann es zu Memoryleaks kommen. In .Net sollte immer darauf geachtet werden, dass Finalize korrekt implementiert wird, d.h. dass dort Speicher auf jeden Fall freigegeben wird, damit sollte das eigentlich nicht mehr eintreten können.

    Viele Grüße
    ~blaze~
    @Grüter
    Eine zuverlässige Methode zum Abschuss des Programms ist Application.Exit. Daran ist vom Codestil und auch technisch nix falsch. Es gibt aber unter Umständen auch andere Möglichkeiten

    @ErfinderDesRades
    Application.Exit ist eigentlich komplett richtig denn diese Methode beendet das Programm zuverlässig und 100% sauber: Application.Exit leitet den Aufruf an Application.ExitInternal weiter, welches alle geöffneten Forms durchloopt und diese sauber per Form.RaiseFormClosingOnAppExit und Form.RaiseFormClosedOnAppExit sich und ihre Children schließen lässt.
    Hingegen sendet Form.Close einfach WM_CLOSE an das eigene Handle.

    nafets schrieb:

    Hingegen sendet Form.Close einfach WM_CLOSE an das eigene Handle.
    Ja, und das reicht ja auch - alles annere macht das Anwendungs-Framework.
    Ich muss also überhaupt nix wissen über die Innereien verschiedener Anwendungs-Tötungs-Formen - ich mach einfach genau das, was der User auch macht, wenn er das Form wegklickt.

    ErfinderDesRades schrieb:

    ich mach einfach genau das, was der User auch macht, wenn er das Form wegklickt

    Und genau dasselbe macht Application.Exit auch! Es sendet diesen Aufruf einfach an alle Forms anstatt nur an deine Hauptform. In den meisten Fällen beendet Me.Close ja nicht mal das Programm!

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „nafets“ ()

    @ThePlexian
    @YEE
    @ErfinderDesRades
    Ich möchte noch einen kleinen Nachtrag zum technischen Aspekt loswerden: Nach weiterem Nachforschen sieht es für mich so aus, als ob beide Methoden fast exakt gleich funktionieren. Ich habe noch ein Diagramm angefertigt, welches die Funktionsweise der beiden Methoden Application.Exit und Form.Close zeigt. Mir geht es jetzt übrigens nicht darum was besser sein, sondern einfach darum, was hinter den Kulissen geschieht.



    Hoffentlich ist es für euch interessant zu wissen, was genau intern geschieht. Ich habe alles genau so in das Diagramm übertragen, wie ich es interpretiert habe - ich bin also sehr zuversichtlich, dass alles richtig ist. Man sieht aber auch sehr gut, dass beide Methoden ein sehr ähnliches Vorgehen haben: Beide durchloopen die OwnedForms und schließen diese. ​Form.Close durchloopt noch die ​MdiChildren, diese sind aber meines Wissens auch in ​Application.OpenFormsInternal enthalten.

    Grüße Stefan