Por que a janela do console se fecha imediatamente uma vez exibida minha saída?

158

Estou estudando c # seguindo os guias no MSDN .

Agora, eu apenas tentei o Exemplo 1 ( aqui está o link para o MSDN ) e encontrei um problema: por que a janela do console se fecha imediatamente uma vez exibida minha saída?

using System;

public class Hello1
{
    public static int Main()
    {
        Console.WriteLine("Hello, World!");
        return 0;
    }
}
user962206
fonte
Você pode tentar abrir com o console. Arraste e solte-o no console e pressione "Enter". Presumo que seja um arquivo EXE.
Sajidur Rahman
Se você estiver tentando depurar um programa de linha de comando iniciado por um processo externo, consulte esta pergunta: stackoverflow.com/a/23334014/3195477
UuDdLrLrSs

Respostas:

265

o problema aqui é que o programa Hello World está aparecendo e ele seria fechado imediatamente.
por que é que?

Porque está terminado. Quando os aplicativos de console concluem a execução e retornam de seu mainmétodo, a janela do console associada é fechada automaticamente. Esse é o comportamento esperado.

Se você quiser mantê-lo aberto para fins de depuração, precisará instruir o computador a aguardar um pressionamento de tecla antes de finalizar o aplicativo e fechar a janela.

O Console.ReadLinemétodo é uma maneira de fazer isso. Adicionar esta linha ao final do seu código (imediatamente antes da returninstrução) fará com que o aplicativo aguarde que você pressione uma tecla antes de sair.

Como alternativa, você pode iniciar o aplicativo sem o depurador conectado pressionando Ctrl+ F5no ambiente do Visual Studio, mas isso tem a desvantagem óbvia de impedir o uso dos recursos de depuração, que você provavelmente deseja ao escrever um aplicativo.

O melhor compromisso é provavelmente chamar o Console.ReadLinemétodo apenas ao depurar o aplicativo, envolvendo-o em uma diretiva de pré-processador. Algo como:

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

Você também pode querer que a janela permaneça aberta se uma exceção não capturada for lançada. Para fazer isso você pode colocar o Console.ReadLine();em um finallybloco:

#if DEBUG
    try
    {
        //...
    }
    finally
    {
        Console.WriteLine("Press enter to close...");
        Console.ReadLine();
    }
#endif
Cody Gray
fonte
18
Como alternativa, você pode usar Console.ReadKey ();
PlantationGator
55
Pessoalmente, eu prefiro if (System.Diagnostics.Debugger.IsAttached) Console.ReadLine();.
Sameer Singh
5
Por que executar sem depuração altera esse comportamento? Você acha que deve ser uma experiência mais precisa, e não menos.
Kyle Delaney
@SameerSingh Mais uma linha de código desnecessário sendo compilada no seu binário. Na verdade, eu prefiro essa abordagem de pré-processador.
Joel
@Joel Por que, em geral, devemos nos preocupar com isso hoje em dia?
Alex
66

Ao invés de usar

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

você pode executar seu programa usando Ctrl+ F5(se estiver no Visual Studio). O Visual Studio manterá a janela do console aberta até você pressionar uma tecla.

Nota: Você não pode depurar seu código nesta abordagem.

Bhavik Patel
fonte
Olá usuário. Sou um novo usuário do VS e C # em geral também. O que Ctrl + F5faz diferente que simplesmente Startfaz diferente?
theGreenCabbage
infelizmente, às vezes para de funcionar como esperado.
MaikoID
2
A causa do problema é que o Windows fecha automaticamente a janela do terminal quando o programa para. Outros sistemas manterão a janela aberta automaticamente. Essa é a maneira muito melhor de executar o programa. Não use ReadKey, Read ou ReadLine para esse material, pois isso impede que seu programa seja usado em combinação com outros aplicativos de console e tubulação.
realtime
14

Eu suponho que o motivo pelo qual você não deseja que ele seja fechado no modo de Depuração, é porque você deseja examinar os valores das variáveis ​​etc. Portanto, provavelmente é melhor apenas inserir um ponto de interrupção no fechamento "}" da função principal . Se você não precisar depurar, Ctrl-F5 é a melhor opção.

Rob L
fonte
Surpreendeu nenhuma das outras respostas sugerir isso. É raro que uma resposta com uma nova opção seja adicionada tão tarde após a criação da pergunta.
21416 Scott Chamberlain
13

Isso se comporta da mesma forma para CtrlF5ou F5. Coloque imediatamente antes do final do Mainmétodo.

using System.Diagnostics;

private static void Main(string[] args) {

  DoWork();

  if (Debugger.IsAttached) {
    Console.WriteLine("Press any key to continue . . .");
    Console.ReadLine();
  }
}
user3484993
fonte
7
Apenas a nota, a última linha deve ser Console.ReadKey()para qualquer tecla, Console.ReadLine()espera por introduzir a ser pressionado
Chris
6

O programa é fechado imediatamente porque não há nada que o impeça de fechar. Insira um ponto de interrupção em return 0;ou adicione Console.Read();antes return 0;para impedir que o programa seja fechado.

Robert Rouhani
fonte
5

Estou um pouco atrasado para a festa, mas: nos projetos do Visual Studio 2019 para .NET Core, o console não fecha automaticamente por padrão. Você pode configurar o comportamento através do menu Ferramentas → Opções → Depuração → Geral → Fechar automaticamente o console quando a depuração parar. Se a janela do console fechar automaticamente, verifique se a configuração mencionada não está definida.

O mesmo se aplica aos novos projetos de console de estilo do .NET Framework:

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

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

</Project>

O projeto antigo do .NET Framework ainda fecha incondicionalmente o console no final (a partir do Visual Studio 16.0.1).

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

Vlad
fonte
Esta opção está disponível para mim no VS2017 15.9.4, mas ele não está funcionando para o meu núcleo .net aplicativo 2.1 consola ...
user1073075
@ user1073075: isso é estranho. O recurso funciona para outros destinos?
31419 Vlad
Não. Tentei com um aplicativo de console do .NET framework e ainda não funcionou. (I instalado VS2019 em uma máquina diferente e não funciona Talvez seja um bug no VS17 15.9.4.)
user1073075
Com 2019, ele funciona agora mesmo para projetos WPF: pastebin.com/FpAeV0cW . Mas você tem que instalar o .NET Núcleo 3.
Vlad
5

Se você deseja manter seu aplicativo aberto, é necessário fazer algo para manter seu processo ativo. O exemplo abaixo é o mais simples, a ser colocado no final do seu programa:

while (true) ;

No entanto, isso fará com que a CPU sobrecarregue, pois é forçada a iterar infinitamente.

Neste ponto, você pode optar por usar a System.Windows.Forms.Applicationclasse (mas requer que você adicione System.Windows.Formsreferência):

Application.Run();

Isso não vaza a CPU e funciona com sucesso.

Para evitar adicionar System.Windows.Formsreferências, você pode usar um truque simples, o chamado giro em espera , importando System.Threading:

SpinWait.SpinUntil(() => false);

Isso também funciona perfeitamente e basicamente consiste em um whileloop com uma condição negada retornada pelo método lambda acima. Por que essa CPU não sobrecarrega? Você pode olhar o código fonte aqui ; de qualquer maneira, basicamente espera algum ciclo da CPU antes de repetir.

Você também pode criar um looper de mensagem, que exibe as mensagens pendentes do sistema e processa cada uma delas antes de passar para a próxima iteração, da seguinte maneira:

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

Em seguida, você pode fazer um loop com segurança fazendo algo assim:

while (true)
    ProcessMessageOnce();
Davide Cannizzo
fonte
Eu não sei se isso vaza CPU ou não, mas; funciona com sucesso. Obrigado.
Mumin Ka
4

Como alternativa, você pode adiar o fechamento usando o seguinte código:

System.Threading.Thread.Sleep(1000);

Observe que Sleepestá usando milissegundos.

gotqn
fonte
4

Outra maneira é usar Debugger.Break()antes de retornar do método Main

dimaaan
fonte
Embora essas opções voltem para a janela do depurador e ocultem potencialmente o conteúdo da janela do console.
Stephen Turner
3

O código está concluído. Para continuar, você precisa adicionar este:

Console.ReadLine();

ou

Console.Read();
Ari
fonte
3

Use Console.Read (); para impedir que o programa seja fechado, mas certifique-se de adicionar o Console.Read();código antes da instrução return, ou será um código inacessível.

    Console.Read(); 
    return 0; 

verifique este Console.

Ravi Gadag
fonte
3

Adicionar O Readmétodo para mostrar a saída.

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

Aqui está uma maneira de fazer isso sem envolver Console:

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

O programa será fechado assim que a execução for concluída. Neste caso, quando você return 0;. Esta é a funcionalidade esperada. Se você quiser ver a saída, execute-a manualmente em um terminal ou defina uma espera no final do programa para que fique aberta por alguns segundos (usando a biblioteca de encadeamento).

zellio
fonte
0

esta é a resposta assíncrona no aplicativo de console em c #?

qualquer coisa que o aplicativo do console nunca use, awaitmas use theAsyncMethod().GetAwaiter().GetResult();,

exemplo

var result = await HttpClientInstance.SendAsync(message);

torna-se

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

bresleveloper
fonte
-3

se o seu programa exigir que você pressione enter para continuar, como você precisa digitar um valor e continuar, adicione um novo double ou int e digite write antes de retunr (0); scanf_s ("% lf", e a variável);

Watifido
fonte
1
Esta é uma pergunta c # .
Wai Ha Lee
-3

Eu sempre adiciono a seguinte declaração a um aplicativo de console (crie um trecho de código para isso, se desejar)

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

Isso ajuda quando você deseja experimentar conceitos diferentes por meio do aplicativo de console.

Ctr + F5 fará com que o console permaneça, mas você não pode depurar! Todos os aplicativos de console que escrevi no mundo real são sempre não interativos e acionados por um Agendador como o TWS ou o CA Work Station e não exigem algo assim.

JAYARAJ SIVADASAN
fonte
-3

Para simplificar o que os outros estão dizendo: Use Console.ReadKey();.

Isso faz com que o programa aguarde o usuário pressionar uma tecla normal no teclado

Fonte: eu uso nos meus programas para aplicativos de console.

Andrew Wilkins
fonte
-3

Você pode resolver isso de maneira muito simples, apenas chamando a entrada. No entanto, se você pressionar Enter, o console irá desaparecer novamente. Basta usar este Console.ReadLine();ouConsole.Read();

gdmanandamohon
fonte
-4

Adicione o seguinte antes do retorno 0:

system("PAUSE");  

Isso imprime uma linha para pressionar uma tecla para fechar a janela. Ele manterá a janela aberta até você pressionar a tecla Enter. Meus alunos o adicionam a todos os seus programas.

Marc
fonte
1
isso é em c ++ #
Gonçalo Garrido
-13

De acordo com minha preocupação, se queremos estabilizar a SAÍDA DO APLICATIVO DO CONSOLE, até o fechamento da saída exibir USE, o rótulo: após o MainMethod e o rótulo goto; antes do final do programa

No programa.

por exemplo:

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

    // Snippet of code

    goto label;
}
NagaHareeshChoudary
fonte
2
Isso fará com que o programa de pôsteres continue imprimindo "Olá, mundo!" muitas vezes #
464 DavidPostill
1
Jesus Cristo, nem sabia que a gotodeclaração era permitida em C #.
Ch3shire