Pourquoi la fenêtre de la console se ferme-t-elle immédiatement une fois ma sortie affichée?

158

J'étudie C # en suivant les guides de MSDN .

Maintenant, je viens d'essayer l' exemple 1 ( voici le lien vers MSDN ), et j'ai rencontré un problème: pourquoi la fenêtre de la console se ferme-t-elle immédiatement une fois ma sortie affichée?

using System;

public class Hello1
{
    public static int Main()
    {
        Console.WriteLine("Hello, World!");
        return 0;
    }
}
user962206
la source
Vous pouvez essayer d'ouvrir avec la console. Faites-le glisser et déposez-le sur la console et appuyez sur "Entrée". Je suppose que c'est un fichier EXE.
Sajidur Rahman
Si vous essayez de DEBUGER un programme de ligne de commande qui est démarré par un processus externe, consultez cette question: stackoverflow.com/a/23334014/3195477
UuDdLrLrSs

Réponses:

267

le problème ici est que leur programme Hello World apparaît, puis il se fermera immédiatement.
pourquoi donc?

Parce que c'est fini. Lorsque les applications de la console ont terminé l'exécution et retournent de leur mainméthode, la fenêtre de la console associée se ferme automatiquement. Il s'agit d'un comportement attendu.

Si vous souhaitez le garder ouvert à des fins de débogage, vous devrez demander à l'ordinateur d'attendre une pression sur une touche avant de mettre fin à l'application et de fermer la fenêtre.

La Console.ReadLineméthode est une façon de faire cela. Si vous ajoutez cette ligne à la fin de votre code (juste avant l' returninstruction), l'application attendra que vous appuyiez sur une touche avant de quitter.

Vous pouvez également démarrer l'application sans le débogueur attaché en appuyant sur Ctrl+ à F5partir de l'environnement Visual Studio, mais cela présente l'inconvénient évident de vous empêcher d'utiliser les fonctionnalités de débogage, que vous souhaitez probablement à votre disposition lors de l'écriture d'une application.

Le meilleur compromis est probablement d'appeler la Console.ReadLineméthode uniquement lors du débogage de l'application en l'enveloppant dans une directive de préprocesseur. Quelque chose comme:

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

Vous pouvez également souhaiter que la fenêtre reste ouverte si une exception non interceptée a été levée. Pour ce faire, vous pouvez mettre le Console.ReadLine();dans un finallybloc:

#if DEBUG
    try
    {
        //...
    }
    finally
    {
        Console.WriteLine("Press enter to close...");
        Console.ReadLine();
    }
#endif
Cody Gray
la source
18
Vous pouvez également utiliser Console.ReadKey ();
PlantationGator
55
Personnellement, je préfère if (System.Diagnostics.Debugger.IsAttached) Console.ReadLine();.
Sameer Singh
5
Pourquoi l'exécution sans débogage change-t-elle ce comportement? Vous penseriez que ce devrait être une expérience plus précise, pas moins.
Kyle Delaney
@SameerSingh Une ligne de plus de code inutile en cours de compilation dans votre binaire. Je préfère en fait cette approche préprocesseur.
Joel
@Joel Pourquoi devrions-nous, en général, nous soucier de cela ces jours-ci?
Alex le
66

À la place d'utiliser

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

vous pouvez exécuter votre programme en utilisant Ctrl+ F5(si vous êtes dans Visual Studio). Ensuite, Visual Studio gardera la fenêtre de la console ouverte jusqu'à ce que vous appuyiez sur une touche.

Remarque: vous ne pouvez pas déboguer votre code dans cette approche.

Bhavik Patel
la source
Salut utilisateur. Je suis également un nouvel utilisateur de VS et de C # en général. Qu'est-ce qui Ctrl + F5fait différemment qui fait tout simplement Startdifféremment?
theGreenCabbage
malheureusement, il s'arrête parfois de fonctionner comme prévu.
MaikoID
2
La cause du problème est que Windows ferme automatiquement la fenêtre du terminal lorsque le programme s'arrête. D'autres systèmes garderont la fenêtre ouverte automatiquement. C'est la meilleure façon d'exécuter le programme. N'utilisez pas ReadKey, Read ou ReadLine pour ce genre de choses car cela empêche votre programme d'être utilisé en combinaison avec d'autres applications de console et de canalisation.
temps réel du
14

Je suppose que la raison pour laquelle vous ne voulez pas qu'il se ferme en mode Débogage, c'est parce que vous voulez regarder les valeurs des variables etc. Il est donc probablement préférable d'insérer simplement un point d'arrêt sur la fermeture "}" de la fonction principale . Si vous n'avez pas besoin de déboguer, alors Ctrl-F5 est la meilleure option.

Rob L
la source
Surpris, aucune des autres réponses n'a suggéré cela. Il est rare qu'une réponse avec une nouvelle option soit ajoutée si tard après la création de la question.
Scott Chamberlain
13

Cela se comporte de la même manière pour CtrlF5ou F5. Placer immédiatement avant la fin de la Mainméthode.

using System.Diagnostics;

private static void Main(string[] args) {

  DoWork();

  if (Debugger.IsAttached) {
    Console.WriteLine("Press any key to continue . . .");
    Console.ReadLine();
  }
}
user3484993
la source
7
Juste à noter, la dernière ligne devrait être Console.ReadKey()pour n'importe quelle touche, Console.ReadLine()attend que vous appuyiez sur Entrée
Chris
6

Le programme se ferme immédiatement car rien ne l'empêche de se fermer. Insérez un point d'arrêt à return 0;ou ajoutez Console.Read();avant return 0;pour empêcher le programme de se fermer.

Robert Rouhani
la source
5

Je suis un peu en retard à la fête, mais: dans Visual Studio 2019 pour les projets .NET Core, la console ne se ferme pas automatiquement par défaut. Vous pouvez configurer le comportement via le menu Outils → Options → Débogage → Général → Fermer automatiquement la console lorsque le débogage s'arrête. Si vous obtenez la fermeture automatique de la fenêtre de votre console, vérifiez si le paramètre mentionné n'est pas défini.

La même chose s'applique aux projets de console de nouveau style .NET Framework:

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

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

</Project>

L'ancien projet .NET Framework ferme toujours inconditionnellement la console à la fin (à partir de Visual Studio 16.0.1).

Référence: https://devblogs.microsoft.com/dotnet/net-core-tooling-update-for-visual-studio-2019-preview-2/

Vlad
la source
Cette option est disponible pour moi dans VS2017 15.9.4 mais elle ne fonctionne pas pour mon application console .net core 2.1 ...
user1073075
@ user1073075: c'est étrange. La fonctionnalité fonctionne-t-elle pour d'autres cibles?
Vlad
Non. Essayé avec une application de console .NET Framework et ne fonctionne toujours pas. (J'ai installé VS2019 sur une machine différente et là ça marche. Peut-être que c'est un bogue dans VS17 15.9.4)
user1073075
Avec 2019, cela fonctionne maintenant même pour les projets WPF: pastebin.com/FpAeV0cW . Mais vous devez installer .NET Core 3.
Vlad
5

Si vous souhaitez garder votre application ouverte, vous devez faire quelque chose pour maintenir son processus en vie. L'exemple ci-dessous est le plus simple, à mettre à la fin de votre programme:

while (true) ;

Cependant, cela entraînera une surcharge du processeur, car il est donc obligé d'itérer à l'infini.

À ce stade, vous pouvez choisir d'utiliser la System.Windows.Forms.Applicationclasse (mais cela vous oblige à ajouter une System.Windows.Formsréférence):

Application.Run();

Cela ne fuit pas le processeur et fonctionne avec succès.

Afin d'éviter d'ajouter une System.Windows.Formsréférence, vous pouvez utiliser une astuce simple, la soi-disant attente de rotation , en important System.Threading:

SpinWait.SpinUntil(() => false);

Cela fonctionne également parfaitement et consiste essentiellement en une whileboucle avec une condition négative renvoyée par la méthode lambda ci-dessus. Pourquoi ce processeur ne surcharge-t-il pas? Vous pouvez consulter le code source ici ; Quoi qu'il en soit, il attend essentiellement un cycle du processeur avant de recommencer.

Vous pouvez également créer un boucleur de messages, qui examine les messages en attente du système et traite chacun d'eux avant de passer à l'itération suivante, comme suit:

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

Ensuite, vous pouvez boucler en toute sécurité en faisant quelque chose comme ceci:

while (true)
    ProcessMessageOnce();
Davide Cannizzo
la source
Je ne sais pas si cela fuit le processeur ou non mais; fonctionne avec succès. Je vous remercie.
Mumin Ka le
4

Vous pouvez également retarder la fermeture à l'aide du code suivant:

System.Threading.Thread.Sleep(1000);

Notez que le Sleeputilise des millisecondes.

gotqn
la source
4

Une autre façon est d'utiliser Debugger.Break()avant de revenir de la méthode Main

dimaaan
la source
Bien que ce commutateur se concentre sur la fenêtre du débogueur et masque potentiellement le contenu de la fenêtre de la console.
Stephen Turner
3

Le code est terminé, pour continuer, vous devez ajouter ceci:

Console.ReadLine();

ou

Console.Read();
Ari
la source
3

Utilisez Console.Read (); pour empêcher le programme de se fermer, mais assurez-vous d'ajouter le Console.Read();code avant l'instruction return, sinon ce sera un code inaccessible.

    Console.Read(); 
    return 0; 

vérifiez cette console.

Ravi Gadag
la source
3

Add La Readméthode pour afficher la sortie.

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

Voici une façon de le faire sans impliquer Console:

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

Le programme se ferme dès que son exécution est terminée. Dans ce cas, lorsque vous return 0;. C'est une fonctionnalité attendue. Si vous voulez voir la sortie, exécutez-la manuellement dans un terminal ou définissez une attente à la fin du programme afin qu'elle reste ouverte pendant quelques secondes (en utilisant la bibliothèque de threads).

zellio
la source
0

c'est la réponse asynchrone à l'application console en C #?

n'importe où dans l'application console, n'utilisez jamais awaitmais utilisez plutôt theAsyncMethod().GetAwaiter().GetResult();,

exemple

var result = await HttpClientInstance.SendAsync(message);

devient

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

développeur
la source
-3

si votre programme vous oblige à appuyer sur Entrée pour continuer comme vous devez entrer une valeur et continuer, ajoutez un nouveau double ou int et tapez write avant retunr (0); scanf_s ("% lf", & la variable);

Watifido
la source
1
C'est une question C # .
Wai Ha Lee
-3

J'ajoute toujours l'instruction suivante à une application console (créez un extrait de code pour cela si vous le souhaitez)

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

Cela aide lorsque vous souhaitez expérimenter différents concepts via une application console.

Ctr + F5 fera rester la console mais vous ne pouvez pas déboguer! Toutes les applications console que j'ai écrites dans realworld sont toujours non interactives et déclenchées par un planificateur tel que TWS ou CA Work station et ne nécessitent pas quelque chose comme ça.

JAYARAJ SIVADASAN
la source
-3

Pour simplifier ce que les autres disent: utilisez Console.ReadKey();.

Cela permet au programme d'attendre que l'utilisateur appuie sur une touche normale du clavier

Source: je l'utilise dans mes programmes pour les applications console.

Andrew Wilkins
la source
-3

Vous pouvez le résoudre de manière très simple en invoquant simplement l'entrée. Cependant, si vous appuyez sur, Enterla console disparaîtra à nouveau. Utilisez simplement ceci Console.ReadLine();ouConsole.Read();

gdmanandamohon
la source
-4

Ajoutez ce qui suit avant le retour 0:

system("PAUSE");  

Cela imprime une ligne pour frapper une touche pour fermer la fenêtre. Il gardera la fenêtre ouverte jusqu'à ce que vous appuyiez sur la touche Entrée. Je demande à mes étudiants de l'ajouter à tous leurs programmes.

Marc
la source
1
thats is in c ++
Gonçalo Garrido
-13

Selon ma préoccupation, si nous voulons stabiliser la SORTIE DE L'APPLICATION CONSOLE, jusqu'à la fermeture de la sortie affiche USE, le label: après la MainMethod, et goto label; avant la fin du programme

Dans le programme.

par exemple:

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

    // Snippet of code

    goto label;
}
NagaHareeshChoudary
la source
2
Le programme d'affiches continuera à imprimer "Hello, World!" plusieurs fois
DavidPostill
1
Jésus-Christ, ne savait même pas que la gotodéclaration était autorisée en C #.
Ch3shire