¿Por qué la ventana de la consola se cierra inmediatamente una vez que aparece mi salida?

158

Estoy estudiando C # siguiendo las guías en MSDN .

Ahora, acabo de probar el Ejemplo 1 ( aquí está el enlace a MSDN ), y he encontrado un problema: ¿por qué la ventana de la consola se cierra inmediatamente una vez que se muestra mi salida?

using System;

public class Hello1
{
    public static int Main()
    {
        Console.WriteLine("Hello, World!");
        return 0;
    }
}
usuario962206
fuente
Puedes intentar abrir con la consola. Arrástrelo y suéltelo en la consola y presione "Entrar". Supongo que es un archivo EXE.
Sajidur Rahman el
Si está intentando DEPURAR un programa de línea de comandos que se inicia mediante un proceso externo, consulte esta pregunta: stackoverflow.com/a/23334014/3195477
UuDdLrLrSs el

Respuestas:

266

El problema aquí es que su Programa Hello World está apareciendo y luego se cerrará de inmediato.
¿porqué es eso?

Porque ya está terminado. Cuando las aplicaciones de consola han completado la ejecución y el retorno de su mainmétodo, la ventana de consola asociada se cierra automáticamente. Este es el comportamiento esperado.

Si desea mantenerlo abierto para fines de depuración, deberá indicarle a la computadora que espere a presionar una tecla antes de finalizar la aplicación y cerrar la ventana.

El Console.ReadLinemétodo es una forma de hacerlo. Agregar esta línea al final de su código (justo antes de la returndeclaración) hará que la aplicación espere a que presione una tecla antes de salir.

Alternativamente, puede iniciar la aplicación sin el depurador conectado presionando Ctrl+ F5desde el entorno de Visual Studio, pero esto tiene la desventaja obvia de evitar que use las funciones de depuración, que probablemente quiera tener a su disposición al escribir una aplicación.

El mejor compromiso es probablemente llamar al Console.ReadLinemétodo solo cuando depure la aplicación envolviéndola en una directiva de preprocesador. Algo como:

#if DEBUG
    Console.WriteLine("Press enter to close...");
    Console.ReadLine();
#endif

También es posible que desee que la ventana permanezca abierta si se produce una excepción no detectada. Para hacer eso puedes poner el Console.ReadLine();en un finallybloque:

#if DEBUG
    try
    {
        //...
    }
    finally
    {
        Console.WriteLine("Press enter to close...");
        Console.ReadLine();
    }
#endif
Cody Gray
fuente
18
Alternativamente, puede usar Console.ReadKey ();
PlantationGator
55
Personalmente, lo prefiero if (System.Diagnostics.Debugger.IsAttached) Console.ReadLine();.
Sameer Singh
55
¿Por qué correr sin depurar cambia ese comportamiento? Uno pensaría que debería ser una experiencia más precisa, no menos.
Kyle Delaney
@SameerSingh Se está compilando una línea más de código innecesario en su binario. De hecho, prefiero este enfoque de preprocesador.
Joel
@ Joel ¿Por qué deberíamos, en general, preocuparnos por eso en estos días?
Alex
66

En lugar de usar

Console.Readline()
Console.Read()
Console.ReadKey()

puedes ejecutar tu programa usando Ctrl+ F5(si estás en Visual Studio). Luego, Visual Studio mantendrá abierta la ventana de la consola, hasta que presione una tecla.

Nota: No puede depurar su código en este enfoque.

Bhavik Patel
fuente
Hola usuario Soy un nuevo usuario de VS y C # en general también. ¿Qué hace Ctrl + F5diferente que simplemente bonito Starthace diferente?
theGreenCabbage
desafortunadamente, a veces deja de funcionar como se esperaba.
MaikoID
2
La causa del problema es que Windows cierra automáticamente la ventana del terminal cuando el programa se detiene. Otros sistemas mantendrán la ventana abierta automáticamente. Esta es la mejor manera de ejecutar el programa. No use ReadKey, Read o ReadLine para estas cosas, ya que esto evita que su programa se use en combinación con otras aplicaciones de consola y tuberías.
tiempo real
14

Supongo que la razón por la que no desea que se cierre en modo de depuración es porque desea ver los valores de las variables, etc. Por lo tanto, probablemente sea mejor insertar un punto de interrupción en el cierre "}" de la función principal . Si no necesita depurar, entonces Ctrl-F5 es la mejor opción.

Rob L
fuente
Sorprendido, ninguna de las otras respuestas sugirió esto. Es raro que una respuesta con una nueva opción que se agrega tan tarde después de que se creó la pregunta.
Scott Chamberlain
13

Esto se comporta igual para CtrlF5o F5. Colocar inmediatamente antes del final del Mainmétodo.

using System.Diagnostics;

private static void Main(string[] args) {

  DoWork();

  if (Debugger.IsAttached) {
    Console.WriteLine("Press any key to continue . . .");
    Console.ReadLine();
  }
}
usuario3484993
fuente
77
Solo para tener en cuenta, la última línea debe ser Console.ReadKey()para cualquier tecla, Console.ReadLine()espera a que se presione Enter
Chris
6

El programa se cierra inmediatamente porque no hay nada que lo detenga. Inserte un punto de interrupción en return 0;o agregue Console.Read();antes return 0;para evitar que el programa se cierre.

Robert Rouhani
fuente
5

Llego un poco tarde a la fiesta, pero: en Visual Studio 2019 para proyectos .NET Core, la consola no se cierra automáticamente de forma predeterminada. Puede configurar el comportamiento a través del menú Herramientas → Opciones → Depuración → General → Cerrar automáticamente la consola cuando se detiene la depuración. Si la ventana de la consola se cierra automáticamente, verifique si la configuración mencionada no está establecida.

Lo mismo se aplica a los proyectos de consola de estilo nuevo de .NET Framework:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net472</TargetFramework>
  </PropertyGroup>

</Project>

El antiguo proyecto de .NET Framework todavía cierra incondicionalmente la consola al final (a partir de Visual Studio 16.0.1).

Referencia: https://devblogs.microsoft.com/dotnet/net-core-tooling-update-for-visual-studio-2019-preview-2/

Vlad
fuente
Esta opción está disponible para mí en VS2017 15.9.4 pero no funciona para mi aplicación de consola .net core 2.1 ...
user1073075
@ user1073075: esto es extraño. ¿Funciona la función para otros objetivos?
Vlad
No. Intenté con una aplicación de consola .NET Framework y aún no funcionó. (He instalado VS2019 en una máquina diferente y no funciona Tal vez sea un error en vs17 15.9.4.)
user1073075
Con 2019 funciona ahora incluso para proyectos de WPF: pastebin.com/FpAeV0cW . Pero tienes que instalar .NET Core 3.
Vlad
5

Si desea mantener abierta su aplicación, debe hacer algo para mantener vivo su proceso. El siguiente ejemplo es el más simple, que se colocará al final de su programa:

while (true) ;

Sin embargo, hará que la CPU se sobrecargue, ya que por lo tanto se ve obligada a iterar infinitamente.

En este punto, puede optar por usar la System.Windows.Forms.Applicationclase (pero requiere que agregue System.Windows.Formsreferencia):

Application.Run();

Esto no pierde la CPU y funciona con éxito.

Para evitar agregar System.Windows.Formsreferencias, puede usar un simple truco, el llamado giro en espera , importando System.Threading:

SpinWait.SpinUntil(() => false);

Esto también funciona perfectamente, y básicamente consiste en un whilebucle con una condición negada que es devuelta por el método lambda anterior. ¿Por qué no se sobrecarga esta CPU? Puedes ver el código fuente aquí ; de todos modos, básicamente espera un ciclo de CPU antes de repetir.

También puede crear un bucleador de mensajes, que mira los mensajes pendientes del sistema y procesa cada uno de ellos antes de pasar a la siguiente iteración, de la siguiente manera:

[DebuggerHidden, DebuggerStepperBoundary, DebuggerNonUserCode, DllImport("user32.dll", EntryPoint = "PeekMessage")]
public static extern int PeekMessage(out NativeMessage lpMsg, IntPtr hWnd, int wMsgFilterMin, int wMsgFilterMax, int wRemoveMsg);

[DebuggerHidden, DebuggerStepperBoundary, DebuggerNonUserCode, DllImport("user32.dll", EntryPoint = "GetMessage")]
public static extern int GetMessage(out NativeMessage lpMsg, IntPtr hWnd, int wMsgFilterMin, int wMsgFilterMax);

[DebuggerHidden, DebuggerStepperBoundary, DebuggerNonUserCode, DllImport("user32.dll", EntryPoint = "TranslateMessage")]
public static extern int TranslateMessage(ref NativeMessage lpMsg);

[DebuggerHidden, DebuggerStepperBoundary, DebuggerNonUserCode, DllImport("user32.dll", EntryPoint = "DispatchMessage")]
public static extern int DispatchMessage(ref NativeMessage lpMsg);

[DebuggerHidden, DebuggerStepperBoundary, DebuggerNonUserCode]
public static bool ProcessMessageOnce()
{
    NativeMessage message = new NativeMessage();

    if (!IsMessagePending(out message))
        return true;

    if (GetMessage(out message, IntPtr.Zero, 0, 0) == -1)
        return true;

    Message frameworkMessage = new Message()
    {
        HWnd = message.handle,
        LParam = message.lParam,
        WParam = message.wParam,
        Msg = (int)message.msg
    };

    if (Application.FilterMessage(ref frameworkMessage))
        return true;

    TranslateMessage(ref message);
    DispatchMessage(ref message);

    return false;
}

Luego, puede realizar un bucle de forma segura haciendo algo como esto:

while (true)
    ProcessMessageOnce();
Davide Cannizzo
fuente
No sé si esto pierde la CPU o no, pero; funciona con exito. Gracias.
Mumin Ka
4

Alternativamente, puede retrasar el cierre con el siguiente código:

System.Threading.Thread.Sleep(1000);

Tenga en cuenta que Sleepestá utilizando milisegundos.

gotqn
fuente
4

Otra forma es usar Debugger.Break()antes de regresar del método Main

dimaaan
fuente
Aunque esto cambia el foco de nuevo a la ventana del depurador y potencialmente oculta el contenido de la ventana de la consola.
Stephen Turner
3

El código está terminado, para continuar necesita agregar esto:

Console.ReadLine();

o

Console.Read();
Ari
fuente
3

Use Console.Read (); para evitar que el programa se cierre, pero asegúrese de agregar el Console.Read();código antes de la declaración de devolución, de lo contrario será un código inalcanzable.

    Console.Read(); 
    return 0; 

revisa esta consola.

Ravi Gadag
fuente
3

Agregar El Readmétodo para mostrar la salida.

Console.WriteLine("Hello, World!");
Console.Read();
return 0;
John Woo
fuente
1

Aquí hay una manera de hacerlo sin involucrar Console:

var endlessTask = new TaskCompletionSource<bool>().Task;
endlessTask.Wait();
Andriy Kozachuk
fuente
0

El programa se cierra tan pronto como se completa su ejecución. En este caso cuando tú return 0;. Esta es la funcionalidad esperada. Si desea ver el resultado, ejecútelo manualmente en un terminal o establezca una espera al final del programa para que permanezca abierto durante unos segundos (utilizando la biblioteca de subprocesos).

zellio
fuente
0

esta es la respuesta asincrónico en aplicación de consola en C #?

nada dondequiera en la aplicación de la consola nunca uso await, pero en lugar de utilizar theAsyncMethod().GetAwaiter().GetResult();,

ejemplo

var result = await HttpClientInstance.SendAsync(message);

se convierte

var result = HttpClientInstance.SendAsync(message).GetAwaiter().GetResult();

bresleveloper
fuente
-3

si su programa requiere que presione enter para continuar, como si tuviera que ingresar un valor y continuar, luego agregue un nuevo doble o int y escriba write antes de retunr (0); scanf_s ("% lf", y la variable);

Watifido
fuente
1
Esta es una pregunta de C # .
Wai Ha Lee
-3

Siempre agrego la siguiente declaración a una aplicación de consola. (Si lo desea, cree un fragmento de código para esto)

Console.WriteLine("Press any key to quit!");
Console.ReadKey();

Hacer esto ayuda cuando quieres experimentar diferentes conceptos a través de la aplicación de consola.

¡Ctr + F5 hará que la consola se quede pero no puede depurar! Todas las aplicaciones de consola que he escrito en el mundo real siempre son no interactivas y son activadas por un Programador como la estación de trabajo TWS o CA y no requieren algo como esto.

JAYARAJ SIVADASAN
fuente
-3

Para simplificar lo que otros dicen: use Console.ReadKey();.

Esto hace que el programa esté esperando que el usuario presione una tecla normal en el teclado

Fuente: Lo uso en mis programas para aplicaciones de consola.

Andrew Wilkins
fuente
-3

Puede resolverlo de manera muy simple simplemente invocando la entrada. Sin embargo, si presiona Enter, la consola volverá a fallar. Simplemente use esto Console.ReadLine();oConsole.Read();

gdmanandamohon
fuente
-4

Agregue lo siguiente antes del retorno 0:

system("PAUSE");  

Esto imprime una línea para presionar una tecla para cerrar la ventana. Mantendrá la ventana abierta hasta que presione la tecla Intro. Mis alumnos lo agregan a todos sus programas.

Bagazo
fuente
1
eso está en c ++
Gonçalo Garrido
-13

Según mi preocupación, si queremos estabilizar la APLICACIÓN DE LA SALIDA DE LA CONSOLA, hasta el cierre de la salida, se muestra USE, la etiqueta: después de MainMethod y goto label; antes del final del programa

En el programa.

p.ej:

static void Main(string[] args)
{
    label:

    // Snippet of code

    goto label;
}
NagaHareeshChoudary
fuente
2
Esto solo hará que el programa de carteles siga imprimiendo "¡Hola, mundo!" muchas veces
DavidPostill
1
Jesucristo, no sabía que la gotodeclaración se permitía incluso en C #.
Ch3shire