¿Cómo salir correctamente de una aplicación C #?

197

Tengo una aplicación publicada en C #. El problema aquí es que cada vez que cierro el formulario principal haciendo clic en el botón rojo de salida, cierra el formulario pero no cierra la aplicación. Descubrí esto cuando intenté apagar la computadora, con la esperanza de que la aplicación que ejecuté funcionara sin problemas y luego fui bombardeado por muchas ventanas secundarias con las que puse MessageBoxAlerts.

Lo intenté Application.Exitpero todavía llama a todas las ventanas y alertas secundarias y no sé cómo usar Environment.Exity qué número entero poner en él.

Por cierto, cada vez que mis formularios llaman al evento formclosedo form closingcierro la aplicación con una this.Hide()función; ¿Afecta eso el comportamiento de mi aplicación ahora?

John Ernest Guadalupe
fuente
2
No maneje FormClosed o FormClosing
SLaks
1
¿Entonces dice que solo está ocultando los formularios en lugar de cerrarlos ? Esa es probablemente la razón por la cual la aplicación no está finalizando, todavía tiene formas abiertas (ocultas).
Xint0
Entonces debería reemplazar todo el this.Hide () a this.Close ()?
John Ernest Guadalupe
1
No necesita Ocultar () o Cerrar ().
Henk Holterman
1
Publique el código sobre acciones y eventos cercanos.
Henk Holterman

Respuestas:

329

De MSDN:

Application.Exit

Informa a todas las bombas de mensajes que deben terminar, y luego cierra todas las ventanas de la aplicación después de que se hayan procesado los mensajes. Este es el código a usar si se le ha llamado Application.Run (aplicaciones WinForms), este método detiene todos los bucles de mensajes en ejecución en todos los hilos y cierra todas las ventanas de la aplicación.

Entorno Salir

Termina este proceso y le da al sistema operativo subyacente el código de salida especificado. Este es el código para llamar cuando está utilizando la aplicación de consola.

Este artículo, Application.Exit vs. Environment.Exit , apunta hacia un buen consejo:

Puede determinar si System.Windows.Forms.Application.Runse ha llamado al verificar la System.Windows.Forms.Application.MessageLooppropiedad. Si es verdadero, se ha llamado a Ejecutar y puede asumir que una aplicación WinForms se está ejecutando de la siguiente manera.

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

Referencia: ¿Por qué Application.Exit no funcionaría?

Furqan Safdar
fuente
Esto fue realmente útil para mí, ya que tenía una aplicación WinForms que tenía un argumento para que pudiera ejecutarse en silencio y, por lo tanto, no mostraba un formulario. Cuando el formulario estaba oculto, Application.Exit()no pudo salir de la aplicación, pero Environment.Exit(1)funcionó de maravilla.
Dib
55
La pregunta no mencionaba la salida debido a un error, por lo que el código de salida debería ser cero: Environment.Exit(0) cualquier valor distinto de cero debe ser un código de error específico de la aplicación que podría ser utilizado por un script para tomar las medidas apropiadas. (Esto es nuevo código y una aplicación de Windows Forms, por lo que es poco probable que importa en este caso, pero bueno saber para escribir cualquier herramientas de línea de comandos.)
YipYip
Environment.Exittambién se puede usar para la aplicación de formularios.
Badiparmagi
1
Corríjame si me equivoco, pero creo que una returndeclaración posterior mejoraría mucho este enfoque. Como entendí, el código continuaría ejecutándose después de Application.Exit()hasta una returndeclaración.
Bighted19
17

Sé que este no es el problema que tuvo, sin embargo, otra razón por la que esto podría suceder es que tiene un hilo de fondo abierto en su aplicación.

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);
            }
        }
    }
}

Cuando IsBackgroundse falseva a mantener su programa abierto hasta que se complete el hilo, si se establece IsBackgroundque trueel hilo no se mantendrá el programa abierto. Cosas como BackgroundWoker, ThreadPooly Tasktodos usan internamente un hilo con IsBackgroundset to true.

Scott Chamberlain
fuente
14

Todo lo que necesitas es System.Environment.Exit(1);

Y usa el espacio de nombres del sistema "usando el sistema" que casi siempre está ahí cuando comienzas un proyecto.

Omar Moodie
fuente
2
Es más adecuado solo para aplicaciones de consola.
Nidhin David
Una cosa a tener en cuenta es que los eventos FormClosing / FormClosed no se llamarán para Environment.Exit también exitCode solo debe ser distinto de cero si se produjo un error,
Raphael Smit
9

Yo haría cualquiera de los siguientes:

Application.Exit ();

para una forma de victoria o

Environment.Exit (0);

para una aplicación de consola (también funciona en winforms).

¡Gracias!

Techcraft7
fuente
Environment.Exit (0) también funciona para WinForms, existe la aplicación sin lanzar ninguna excepción.
MulleOne
8

Por cierto. cada vez que mis formularios llaman al evento de cierre de formulario o de cierre de formulario, cierro la aplicación con una función this.Hide (). ¿Afecta eso el comportamiento de mi aplicación ahora?

En resumen, si. La aplicación completa finalizará cuando el formulario principal (el formulario que se inició a través Application.Rundel Mainmétodo) esté cerrado (no oculto).

Si su aplicación completa siempre debe terminar por completo cada vez que se cierra su formulario principal, entonces solo debe eliminar ese controlador cerrado de formulario. Al no cancelar ese evento y simplemente dejar que se formen cuando el usuario lo cierra, obtendrá el comportamiento deseado. En cuanto a todos los otros formularios, si no tiene la intención de mostrar la misma instancia del formulario nuevamente, simplemente déjelos cerrar, en lugar de evitar el cierre y ocultarlos. Si los está mostrando nuevamente, entonces ocultarlos puede estar bien.

Si desea que el usuario haga clic en la "x" para su formulario principal, pero que otro formulario permanezca abierto y, en efecto, se convierta en el "formulario principal" nuevo, entonces es un poco más complicado. En tal caso, deberá ocultar su formulario principal en lugar de cerrarlo, pero deberá agregar algún tipo de mecanismo que realmente cierre el formulario principal cuando realmente desee que su aplicación finalice. Si esta es la situación en la que se encuentra, deberá agregar más detalles a su pregunta que describa qué tipos de aplicaciones deberían y no deberían finalizar el programa.

Servy
fuente
3

Haces:

Application.Run(myForm);

en su Main ()?

Me pareció una forma muy fácil de eliminar la aplicación cuando se cierra el formulario.

LightStriker
fuente
1
sí, tiene Application.Run en el archivo Program.cs en Main. ¿Qué hago para cerrarlo entonces?
John Ernest Guadalupe
Pero pasas tu formulario principal a Run, ¿verdad? El formulario que cierra haciendo clic en la X roja.
LightStriker
Sí, lo tengo, señor. Es así: Application.Run (new Form2 ());
John Ernest Guadalupe
En ese caso, si el formulario principal pasado a Ejecutar estuviera realmente completamente cerrado, la aplicación se cerraría automáticamente. Luego debe rastrear por qué ese formulario aún está abierto, ejecutándose u oculto en algún lugar.
LightStriker
3
Environment.Exit(exitCode); //exit code 0 is a proper exit and 1 is an error
joe pelletier
fuente
-4

En este caso, la forma más adecuada de salir de la aplicación para anular el método onExit () en App.xaml.cs:

protected override void OnExit(ExitEventArgs e) {
    base.OnExit(e); 
}
Anton Tsches
fuente
Eso le permite ejecutar código cada vez que ocurre un evento de salida, pero en realidad no hace que suceda el evento de salida.
jpaugh