Jak poprawnie zamknąć aplikację C #?

197

Mam opublikowaną aplikację w języku C #. Problem polega na tym, że za każdym razem, gdy zamykam główny formularz, klikając czerwony przycisk wyjścia, zamyka on formularz, ale nie zamyka aplikacji. Dowiedziałem się tego, gdy próbowałem wyłączyć komputer, mając nadzieję, że aplikacja, którą stworzyłem, działała płynnie, a następnie zostałem zbombardowany przez wiele okien potomnych, za pomocą których zainstalowałem MessageBoxAlerty.

Próbowałem, Application.Exitale nadal wywołuje wszystkie okna potomne i alerty i nie wiem, jak używać Environment.Exiti jaką liczbę całkowitą w nim umieścić.

Nawiasem mówiąc, za każdym razem, gdy moje formularze wywołują formclosedlub form closingzdarzenie, zamykam aplikację za pomocą this.Hide()funkcji; Czy to wpływa na zachowanie mojej aplikacji?

John Ernest Guadalupe
źródło
2
Nie obsługuj FormClosed ani FormClosing
SLaks
1
Więc mówisz, że ukrywasz formularze zamiast je zamykać ? Prawdopodobnie dlatego aplikacja się nie kończy, nadal ma otwarte (ukryte) formularze.
Xint0,
Następnie powinienem wymienić wszystkie this.Hide () na this.Close ()?
John Ernest Guadalupe
1
Nie potrzebujesz Hide () ani Close ().
Henk Holterman
1
Opublikuj kod dotyczący zamkniętych działań i wydarzeń.
Henk Holterman

Odpowiedzi:

329

Z MSDN:

Application.Exit

Informuje wszystkie pompy komunikatów, że muszą zakończyć, a następnie zamyka wszystkie okna aplikacji po przetworzeniu wiadomości. Jest to kod, który należy zastosować, jeśli nazywa się Application.Run (aplikacje WinForms), ta metoda zatrzymuje wszystkie uruchomione pętle komunikatów we wszystkich wątkach i zamyka wszystkie okna aplikacji.

Environment.Exit

Kończy ten proces i nadaje bazowemu systemowi operacyjnemu określony kod wyjścia. Jest to kod, który należy wywoływać, gdy korzystasz z aplikacji konsoli.

Ten artykuł, Application.Exit vs. Environment.Exit , wskazuje na dobrą wskazówkę:

Możesz sprawdzić, czy System.Windows.Forms.Application.Runzostał wywołany, sprawdzając System.Windows.Forms.Application.MessageLoopwłaściwość. Jeśli true, to wywołano Run i można założyć, że aplikacja WinForm działa w następujący sposób.

if (System.Windows.Forms.Application.MessageLoop) 
{
    // WinForms app
    System.Windows.Forms.Application.Exit();
}
else
{
    // Console app
    System.Environment.Exit(1);
}

Odniesienie: Dlaczego Application.Exit nie działa?

Furqan Safdar
źródło
Było to dla mnie bardzo przydatne, ponieważ miałem aplikację WinForms, która miała argument, dzięki czemu mogła działać cicho, a zatem nie wyświetlała formularza. Gdy formularz został ukryty, Application.Exit()nie udało się zamknąć aplikacji, jednak Environment.Exit(1)działało to jak urok.
Dib,
5
Pytanie nie wspominało o wyjściu z powodu błędu, więc kod wyjścia powinien wynosić zero: Environment.Exit(0) Każda niezerowa wartość ma być specyficznym dla aplikacji kodem błędu, który może być użyty przez skrypt do podjęcia odpowiednich działań. (Jest to nowy kod i aplikacja WinForms, więc w tym przypadku raczej nie ma to znaczenia, ale warto wiedzieć, że ktoś pisze narzędzia wiersza polecenia.)
YipYip,
Environment.Exitmoże być również używany do składania formularzy.
Badiparmagi,
1
Popraw mnie, jeśli się mylę, ale myślę, że returnpóźniej oświadczenie bardzo poprawiłoby to podejście. Jak rozumieć kod będzie kontynuować realizację po Application.Exit()aż w returnoświadczeniu.
Bighted19
17

Wiem, że nie był to twój problem, jednak może to mieć inny powód, ponieważ w aplikacji jest otwarty wątek inny niż tło.

using System;
using System.Threading;
using System.Windows.Forms;

namespace Sandbox_Form
{
    static class Program
    {
        private static Thread thread;

        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            thread = new Thread(BusyWorkThread);
            thread.IsBackground = false;
            thread.Start();

            Application.Run(new Form());

        }

        public static void BusyWorkThread()
        {
            while (true)
            {
                Thread.Sleep(1000);
            }
        }
    }
}

Kiedy IsBackgroundto falsebędzie utrzymywać swój program otwarty aż zakończy wątku, jeśli ustawisz IsBackgrounddo truewątku nie będzie prowadzić program otwarty. Rzeczy takie jak BackgroundWoker, ThreadPooli Taskwszystkie wewnętrznie używają wątku z IsBackgroundustawionym na true.

Scott Chamberlain
źródło
14

Wszystko czego potrzebujesz to System.Environment.Exit(1);

I używa systemowej przestrzeni nazw „using System”, która jest prawie zawsze dostępna podczas uruchamiania projektu.

Omar Moodie
źródło
2
Jest bardziej odpowiedni tylko dla aplikacji konsolowych.
Nidhin David
Należy zwrócić uwagę na to, że zdarzenia FormClosing / FormClosed nie będą wywoływane dla środowiska. Wyjście również kod zakończenia powinien być niezerowy tylko w przypadku wystąpienia błędu,
Raphael Smit
9

Chciałbym jedno z poniższych:

Application.Exit ();

dla winform lub

Environment.Exit (0);

dla aplikacji konsolowej (działa również na WinForm).

Dzięki!

Techcraft7
źródło
Environment.Exit (0) działa również dla WinForms, istnieje aplikacja bez zgłaszania żadnych wyjątków.
MulleOne,
8

Tak poza tym. za każdym razem, gdy moje formularze wywołują zdarzenie formclosed lub zamykające formularz, zamykam aplację za pomocą funkcji this.Hide (). Czy to wpływa na zachowanie mojej aplikacji?

W skrócie tak. Cała aplikacja zakończy się, gdy główny formularz (formularz uruchomiony za Application.Runpomocą Mainmetody) zostanie zamknięty (nie ukryty).

Jeśli cała aplikacja powinna być zawsze w pełni zakończona, gdy tylko główny formularz zostanie zamknięty, należy po prostu usunąć ten zamknięty moduł obsługi. Nie anulując tego wydarzenia i pozwalając mu się zamknąć, gdy użytkownik je zamknie, uzyskasz pożądane zachowanie. Podobnie jak w przypadku wszystkich innych formularzy, jeśli nie zamierzasz ponownie wyświetlać tego samego wystąpienia formularza, po prostu pozwól im się zamknąć, zamiast zapobiegać ich zamknięciu i ukryciu. Jeśli wyświetlasz je ponownie, ukrywanie ich może być w porządku.

Jeśli chcesz, aby użytkownik kliknął „x” dla głównego formularza, ale inny formularz pozostanie otwarty i, w efekcie, stanie się „nową” główną formą, jest to nieco bardziej skomplikowane. W takim przypadku musisz po prostu ukryć główny formularz zamiast go zamykać, ale musisz dodać jakiś mechanizm, który faktycznie zamknie główny formularz, gdy naprawdę chcesz, aby Twoja aplikacja się zakończyła. W takiej sytuacji musisz dodać więcej szczegółów do pytania opisującego, jakie typy aplikacji powinny i nie powinny faktycznie kończyć program.

Servy
źródło
3

Czy ty robisz:

Application.Run(myForm);

w swoim Main ()?

Uznałem, że jest to bardzo łatwy sposób na zabicie aplikacji, gdy formularz jest zamknięty.

LightStriker
źródło
1
tak, ma Application.Run w pliku Program.cs w Main. Co mam wtedy zrobić, żeby to zamknąć?
John Ernest Guadalupe,
Ale przekazujesz swoją główną formę do Run, prawda? Formularz, który
zamykasz,
tak, mam to. Jest tak: Application.Run (new Form2 ());
John Ernest Guadalupe
W takim przypadku, jeśli główny formularz przekazany do Run byłby naprawdę całkowicie zamknięty, aplikacja zamknąłaby się automatycznie. Musisz następnie śledzić, dlaczego ten formularz jest gdzieś nadal otwarty, uruchomiony lub ukryty.
LightStriker,
3
Environment.Exit(exitCode); //exit code 0 is a proper exit and 1 is an error
Joe Pelletier
źródło
-4

W takim przypadku najbardziej właściwym sposobem na zamknięcie aplikacji w celu zastąpienia metody onExit () w App.xaml.cs:

protected override void OnExit(ExitEventArgs e) {
    base.OnExit(e); 
}
Anton Tsches
źródło
Pozwala to na wykonanie kodu za każdym razem, gdy nastąpi zdarzenie wyjściowe, ale tak naprawdę nie powoduje zdarzenia wyjściowego.
jpaugh