Warum wird das Konsolenfenster sofort geschlossen, sobald meine Ausgabe angezeigt wird?

158

Ich lerne C #, indem ich den Anleitungen in MSDN folge .

Jetzt habe ich nur Beispiel 1 ausprobiert ( hier ist der Link zu MSDN ) und bin auf ein Problem gestoßen: Warum wird das Konsolenfenster sofort geschlossen, sobald meine Ausgabe angezeigt wird?

using System;

public class Hello1
{
    public static int Main()
    {
        Console.WriteLine("Hello, World!");
        return 0;
    }
}
user962206
quelle
Sie können versuchen, mit der Konsole zu öffnen. Ziehen Sie es per Drag & Drop auf die Konsole und drücken Sie die Eingabetaste. Ich nehme an, es ist eine EXE-Datei.
Sajidur Rahman
Wenn Sie versuchen, ein Befehlszeilenprogramm zu debuggen, das von einem externen Prozess gestartet wird, lesen
UuDdLrLrSs

Antworten:

265

Das Problem hier ist, dass ihr Hello World-Programm angezeigt wird und dann sofort geschlossen wird.
warum ist das so?

Weil es fertig ist. Wenn die Ausführung von Konsolenanwendungen abgeschlossen ist und von ihrer mainMethode zurückkehrt, wird das zugehörige Konsolenfenster automatisch geschlossen. Dies ist das erwartete Verhalten.

Wenn Sie es für Debugging-Zwecke geöffnet lassen möchten, müssen Sie den Computer anweisen, auf einen Tastendruck zu warten, bevor Sie die App beenden und das Fenster schließen.

Die Console.ReadLineMethode ist eine Möglichkeit, dies zu tun. Wenn Sie diese Zeile am Ende Ihres Codes (kurz vor der returnAnweisung) hinzufügen, wartet die Anwendung vor dem Beenden darauf, dass Sie eine Taste drücken.

Alternativ können Sie die Anwendung ohne den angehängten Debugger starten, indem Sie in der Visual Studio-Umgebung Ctrl+ drücken. F5Dies hat jedoch den offensichtlichen Nachteil, dass Sie nicht die Debugging-Funktionen verwenden können, die Ihnen beim Schreiben einer Anwendung wahrscheinlich zur Verfügung stehen.

Der beste Kompromiss besteht wahrscheinlich darin, die Console.ReadLineMethode nur beim Debuggen der Anwendung aufzurufen, indem sie in eine Präprozessor-Direktive eingeschlossen wird. Etwas wie:

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

Möglicherweise möchten Sie auch, dass das Fenster geöffnet bleibt, wenn eine nicht erfasste Ausnahme ausgelöst wurde. Dazu können Sie das Console.ReadLine();in einen finallyBlock setzen:

#if DEBUG
    try
    {
        //...
    }
    finally
    {
        Console.WriteLine("Press enter to close...");
        Console.ReadLine();
    }
#endif
Cody Grey
quelle
18
Alternativ können Sie Console.ReadKey () verwenden.
PlantationGator
55
Ich persönlich bevorzuge if (System.Diagnostics.Debugger.IsAttached) Console.ReadLine();.
Sameer Singh
5
Warum ändert das Ausführen ohne Debuggen dieses Verhalten? Sie würden denken, es sollte eine genauere Erfahrung sein, nicht weniger.
Kyle Delaney
@SameerSingh Eine weitere Zeile unnötigen Codes wird in Ihre Binärdatei kompiliert. Ich bevorzuge diesen Präprozessor-Ansatz.
Joel
@ Joel Warum sollten wir uns heutzutage im Allgemeinen darum kümmern?
Alex
66

Anstatt zu verwenden

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

Sie können Ihr Programm mit Ctrl+ ausführen F5(wenn Sie sich in Visual Studio befinden). Anschließend lässt Visual Studio das Konsolenfenster geöffnet, bis Sie eine Taste drücken.

Hinweis: Sie können Ihren Code bei diesem Ansatz nicht debuggen.

Bhavik Patel
quelle
Hallo Benutzer. Ich bin auch ein neuer Benutzer von VS und C # im Allgemeinen. Was macht Ctrl + F5anders als einfach hübsch Startanders?
TheGreenCabbage
Leider funktioniert es manchmal nicht mehr wie erwartet.
MaikoID
2
Die Ursache des Problems ist, dass Windows das Terminalfenster automatisch schließt, wenn das Programm beendet wird. Andere Systeme lassen das Fenster automatisch geöffnet. Dies ist der weitaus bessere Weg, um das Programm auszuführen. Verwenden Sie für dieses Material nicht ReadKey, Read oder ReadLine, da dies verhindert, dass Ihr Programm in Kombination mit anderen Konsolenanwendungen und Pipings verwendet wird.
Echtzeit
14

Ich gehe davon aus, dass Sie nicht möchten, dass es im Debug-Modus geschlossen wird, weil Sie sich die Werte von Variablen usw. ansehen möchten. Daher ist es wahrscheinlich am besten, einfach einen Haltepunkt am schließenden "}" der Hauptfunktion einzufügen . Wenn Sie nicht debuggen müssen, ist Strg-F5 die beste Option.

Rob L.
quelle
Überrascht deutete keine der anderen Antworten darauf hin. Es ist selten, dass eine Antwort mit einer neuen Option so spät hinzugefügt wird, nachdem die Frage erstellt wurde.
Scott Chamberlain
13

Dies verhält sich für CtrlF5oder gleich F5. Unmittelbar vor Ende der MainMethode platzieren.

using System.Diagnostics;

private static void Main(string[] args) {

  DoWork();

  if (Debugger.IsAttached) {
    Console.WriteLine("Press any key to continue . . .");
    Console.ReadLine();
  }
}
user3484993
quelle
7
Nur um zu beachten, die letzte Zeile sollte Console.ReadKey()für eine beliebige Taste sein, Console.ReadLine()wartet auf das Drücken der Eingabetaste
Chris
6

Das Programm wird sofort geschlossen, da nichts das Schließen verhindert. Legen Sie einen Haltepunkt an return 0;oder fügen Sie Console.Read();vor , return 0;das Programm vor der Schließung zu verhindern.

Robert Rouhani
quelle
5

Ich bin etwas spät zur Party, aber: In Visual Studio 2019 für .NET Core-Projekte wird die Konsole standardmäßig nicht automatisch geschlossen. Sie können das Verhalten über das Menü Extras → Optionen → Debuggen → Allgemein → Konsole automatisch schließen, wenn das Debuggen beendet wird. Wenn sich Ihr Konsolenfenster automatisch schließt, überprüfen Sie, ob die angegebene Einstellung nicht festgelegt ist.

Gleiches gilt für Konsolenprojekte im neuen Stil von .NET Framework:

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

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

</Project>

Das .NET Framework-Projekt im alten Stil schließt die Konsole am Ende immer noch unbedingt (ab Visual Studio 16.0.1).

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

Vlad
quelle
Diese Option ist für mich in VS2017 15.9.4 verfügbar, funktioniert jedoch nicht für meine .net Core 2.1-Konsolenanwendung ...
user1073075
@ user1073075: das ist seltsam. Funktioniert die Funktion für andere Ziele?
Vlad
Versucht mit einer .NET Framework-Konsolen-App und immer noch nicht funktioniert. (Ich habe VS2019 auf einem anderen Computer installiert und dort funktioniert es. Vielleicht ist es ein Fehler in VS17 15.9.4)
user1073075
Mit 2019 funktioniert es jetzt auch für WPF-Projekte: pastebin.com/FpAeV0cW . Aber Sie müssen .NET Core 3 installieren.
Vlad
5

Wenn Sie Ihre Anwendung geöffnet lassen möchten, müssen Sie etwas tun, um den Prozess am Leben zu erhalten. Das folgende Beispiel ist das einfachste, das am Ende Ihres Programms steht:

while (true) ;

Dies führt jedoch zu einer Überlastung der CPU, da diese daher unendlich iterieren muss.

An dieser Stelle können Sie sich für die Verwendung der System.Windows.Forms.ApplicationKlasse entscheiden (Sie müssen jedoch eine System.Windows.FormsReferenz hinzufügen ):

Application.Run();

Dies leckt keine CPU und funktioniert erfolgreich.

Um das Hinzufügen von System.Windows.FormsReferenzen zu vermeiden , können Sie einen einfachen Trick verwenden, das sogenannte Spin-Warten und Importieren System.Threading:

SpinWait.SpinUntil(() => false);

Dies funktioniert auch perfekt und besteht im Wesentlichen aus einer whileSchleife mit einer negierten Bedingung, die von der obigen Lambda-Methode zurückgegeben wird. Warum ist diese CPU nicht überlastet? Den Quellcode können Sie hier einsehen. Trotzdem wartet es im Grunde einen CPU-Zyklus, bevor es wiederholt wird.

Sie können auch einen Nachrichten-Looper erstellen, der die ausstehenden Nachrichten aus dem System überprüft und verarbeitet, bevor er zur nächsten Iteration übergeht.

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

Dann können Sie sicher eine Schleife ausführen, indem Sie Folgendes tun:

while (true)
    ProcessMessageOnce();
Davide Cannizzo
quelle
Ich weiß nicht, ob dies CPU leckt oder nicht, aber; funktioniert erfolgreich. Danke dir.
Mumin Ka
4

Alternativ können Sie das Schließen mit dem folgenden Code verzögern:

System.Threading.Thread.Sleep(1000);

Beachten Sie Sleep, dass Millisekunden verwendet werden.

gotqn
quelle
4

Eine andere Möglichkeit besteht darin, Debugger.Break()vor der Rückkehr von der Hauptmethode zu verwenden

Dimaaan
quelle
Dadurch wird der Fokus wieder auf das Debugger-Fenster gerichtet und möglicherweise der Inhalt des Konsolenfensters ausgeblendet.
Stephen Turner
3

Der Code ist fertig. Um fortzufahren, müssen Sie Folgendes hinzufügen:

Console.ReadLine();

oder

Console.Read();
Ari
quelle
3

Verwenden Sie Console.Read (); Um zu verhindern, dass das Programm geschlossen wird, stellen Sie jedoch sicher, dass Sie den Console.Read();Code vor der return-Anweisung hinzufügen. Andernfalls handelt es sich um einen nicht erreichbaren Code.

    Console.Read(); 
    return 0; 

Überprüfen Sie diese Console.Read

Ravi Gadag
quelle
3

Hinzufügen Die ReadMethode zum Anzeigen der Ausgabe.

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

Hier ist eine Möglichkeit, dies ohne Beteiligung zu tun Console:

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

Das Programm wird geschlossen, sobald die Ausführung abgeschlossen ist. In diesem Fall, wenn Sie return 0;. Dies ist erwartete Funktionalität. Wenn Sie die Ausgabe sehen möchten, führen Sie sie entweder manuell in einem Terminal aus oder stellen Sie am Ende des Programms eine Wartezeit ein, damit sie einige Sekunden lang geöffnet bleibt (mithilfe der Threading-Bibliothek).

zellio
quelle
0

Dies ist die asynchrone Antwort in der Konsolen-App in C #?

alles, was in der Konsolen-App niemals verwendet wird, awaitsondern stattdessen verwendet wird theAsyncMethod().GetAwaiter().GetResult();,

Beispiel

var result = await HttpClientInstance.SendAsync(message);

wird

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

Bresleveloper
quelle
-3

Wenn Ihr Programm erfordert, dass Sie die Eingabetaste drücken, um fortzufahren, wie Sie einen Wert eingeben und fortfahren müssen, fügen Sie ein neues double oder int hinzu und geben Sie write vor retunr (0) ein. scanf_s ("% lf" & die Variable);

Watifido
quelle
1
Dies ist eine C # -Frage.
Wai Ha Lee
-3

Ich füge einer Konsolenanwendung immer die folgende Anweisung hinzu. (Erstellen Sie dazu ein Code-Snippet, wenn Sie dies wünschen.)

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

Dies ist hilfreich, wenn Sie verschiedene Konzepte über die Konsolenanwendung ausprobieren möchten.

Strg + F5 lässt die Konsole bleiben, aber Sie können nicht debuggen! Alle Konsolenanwendungen, die ich in der realen Welt geschrieben habe, sind immer nicht interaktiv und werden von einem Scheduler wie TWS oder CA Work Station ausgelöst und erforderten so etwas nicht.

JAYARAJ SIVADASAN
quelle
-3

Um zu vereinfachen, was andere sagen: Verwenden Sie Console.ReadKey();.

Dadurch wartet das Programm darauf, dass der Benutzer eine normale Taste auf der Tastatur drückt

Quelle: Ich verwende es in meinen Programmen für Konsolenanwendungen.

Andrew Wilkins
quelle
-3

Sie können es auf sehr einfache Weise lösen, indem Sie einfach die Eingabe aufrufen. Wenn Sie jedoch drücken, Enterwird die Konsole wieder ausgeblendet. Verwenden Sie einfach diese Console.ReadLine();oderConsole.Read();

gdmanandamohon
quelle
-4

Fügen Sie vor der Rückgabe 0 Folgendes hinzu:

system("PAUSE");  

Dadurch wird eine Zeile gedruckt, um eine Taste zum Schließen des Fensters zu drücken. Das Fenster bleibt so lange geöffnet, bis Sie die Eingabetaste drücken. Ich habe meine Schüler es zu allen ihren Programmen hinzufügen.

Marc
quelle
1
das ist in c ++
Gonçalo Garrido
-13

Meiner Sorge nach, wenn wir den AUSGANG DER KONSOLENANWENDUNG stabilisieren möchten, bis zum Ende der Ausgabe USE anzeigen, das Label: nach der MainMethod und goto label; vor Programmende

Im Programm.

z.B:

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

    // Snippet of code

    goto label;
}
NagaHareeshChoudary
quelle
2
Dies führt nur dazu, dass das Posterprogramm weiterhin "Hallo Welt!" Druckt. viele Male
DavidPostill
1
Jesus Christus, wusste nicht, dass eine gotoAussage in C # erlaubt war.
Ch3shire