为什么显示我的输出后立即关闭控制台窗口?


158

我正在按照MSDN中的指南学习C#。

现在,我只是尝试了示例1是指向MSDN的链接),但是我遇到了一个问题:为什么控制台窗口在显示我的输出后立即关闭?

using System;

public class Hello1
{
    public static int Main()
    {
        Console.WriteLine("Hello, World!");
        return 0;
    }
}

您可以尝试使用控制台打开。将其拖放到控制台上,然后按“ Enter”。我假设它是一个EXE文件。
Sajidur Ra​​hman

如果您尝试调试由外部进程启动的命令行程序,请参阅以下问题:stackoverflow.com/a/23334014/3195477
UuDdLrLrSs

Answers:


266

这里的问题是他们的Hello World程序正在显示,然后将立即关闭。
这是为什么?

因为完成了。控制台应用程序完成执行并从其main方法返回后,关联的控制台窗口将自动关闭。这是预期的行为。

如果要使其保持打开状态以进行调试,则需要指示计算机等待按键,然后再结束应用程序并关闭窗口。

Console.ReadLine方法是执行此操作的一种方法。将此行添加到代码末尾(恰好在return语句之前)将使应用程序等待您在退出之前先按下一个键。

或者,您可以通过在Visual Studio环境中按Ctrl+ 来启动没有附加调试器的应用程序F5,但是这样做的明显缺点是阻止您使用调试功能,编写功能时可能需要使用调试功能。

最好的折衷办法可能是Console.ReadLine仅在通过将应用程序包装在预处理程序指令中来调试应用程序时才调用该方法。就像是:

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

如果引发未捕获的异常,您可能还希望窗口保持打开状态。为此,您可以将放在Console.ReadLine();一个finally块中:

#if DEBUG
    try
    {
        //...
    }
    finally
    {
        Console.WriteLine("Press enter to close...");
        Console.ReadLine();
    }
#endif

18
或者,您可以使用Console.ReadKey();。
PlantationGator

55
就个人而言,我更喜欢if (System.Diagnostics.Debugger.IsAttached) Console.ReadLine();
Sameer Singh

5
为什么在不调试的情况下运行会更改该行为?您会认为这应该是更准确的体验,而不是更少。
凯尔·德莱尼

@SameerSingh再将另一行不必要的代码编译到您的二进制文件中。我实际上更喜欢这种预处理器方法。
乔尔

@Joel这些天,为什么我们通常应该关心它?
Alex

66

而不是使用

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

您可以使用Ctrl+ F5(如果您在Visual Studio中)运行程序。然后,Visual Studio将保持控制台窗口打开,直到您按下一个键。

注意:您不能使用这种方法调试代码。


嗨,用户 一般而言,我也是VS和C#的新用户。这是什么Ctrl + F5做什么不同,单纯漂亮Start有什么不同?
theGreenCabbage

不幸的是,有时它会停止按预期工作。
MaikoID 2013年

2
问题的原因是程序停止时,窗口会自动关闭终端窗口。其他系统将自动保持窗口打开。这是运行程序的更好的方法。不要为这些东西使用ReadKey,Read或ReadLine,因为这会阻止您的程序与其他控制台应用程序和管道一起使用。
实时

14

我假设您不希望它在Debug模式下关闭的原因是因为您想查看变量等的值。因此,最好只在主函数的结尾“}”上插入一个断点。如果您不需要调试,则Ctrl-F5是最佳选择。


惊讶的是没有其他答案表明了这一点。在问题创建后这么晚才添加带有新选项的答案的情况很少。
斯科特·张伯伦

13

CtrlF5或的行为相同F5。在Main方法结束前放置。

using System.Diagnostics;

private static void Main(string[] args) {

  DoWork();

  if (Debugger.IsAttached) {
    Console.WriteLine("Press any key to continue . . .");
    Console.ReadLine();
  }
}

7
请注意,最后一行应该是Console.ReadKey()任何键,Console.ReadLine()等待输入被按下
克里斯(Chris


5

我参加聚会有点晚了,但是:在Visual Studio 2019 for .NET Core项目中,默认情况下控制台不会自动关闭。您可以通过菜单工具→选项→调试→常规→在调试停止时自动关闭控制台来配置行为。如果您的控制台窗口自动关闭,请检查是否未设置上述设置。

.NET Framework新型控制台项目也是如此:

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

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

</Project>

旧样式的.NET Framework项目仍然无条件地在最后关闭了控制台(从Visual Studio 16.0.1开始)。

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


该选项在VS2017 15.9.4中对我可用,但不适用于我的.net core 2.1控制台应用程序……
user1073075 '19

@ user1073075:这很奇怪。该功能是否可用于其他目标?
Vlad19年

否。尝试使用.NET Framework控制台应用程序仍然无法正常工作。(我在另一台机器上安装了VS2019,并且在那里工作。也许是VS17 15.9.4中的错误)
user1073075 '19

从2019年起,它现在甚至适用于WPF项目:pastebin.com/FpAeV0cW。但是你必须安装.NET核心3
弗拉德

5

如果要保持打开应用程序的状态,则必须执行一些操作才能使其进程保持活动状态。下面的例子是最简单的例子,放在程序的末尾:

while (true) ;

但是,这将导致CPU过载,因为它被迫无限迭代。

在这一点上,您可以选择使用System.Windows.Forms.Application类(但是它需要您添加System.Windows.Forms引用):

Application.Run();

这不会泄漏CPU,并且可以成功运行。

为了避免添加System.Windows.Forms引用,可以使用一个简单的技巧,即所谓的spin wait,import System.Threading

SpinWait.SpinUntil(() => false);

这也可以完美地工作,并且基本上由while上述lambda方法返回的条件为负的循环组成。为什么不使CPU过载?您可以在这里查看源代码;无论如何,它基本上会等待一些CPU周期再进行迭代。

您还可以创建一个消息循环程序,该消息循环程序将窥探系统中的待处理消息,并在传递到下一个迭代之前对其进行处理,如下所示:

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

然后,您可以通过执行以下操作来安全地循环:

while (true)
    ProcessMessageOnce();

我不知道这是否泄漏CPU;但是,工作成功。谢谢。
Mumin Ka

4

或者,您可以使用以下代码延迟关闭:

System.Threading.Thread.Sleep(1000);

请注意,Sleep使用的是毫秒。


4

另一种方法是Debugger.Break()在从Main方法返回之前使用


尽管此开关将焦点移回到调试器窗口,并可能隐藏控制台窗口的内容。
斯蒂芬·特纳

3

代码已完成,要继续,您需要添加以下代码:

Console.ReadLine();

要么

Console.Read();

3

使用Console.Read(); 以防止程序关闭,但是请确保Console.Read();在return语句之前添加代码,否则它将是无法访问的代码。

    Console.Read(); 
    return 0; 

检查此控制台。阅读


3

添加Read方法以显示输出。

Console.WriteLine("Hello, World!");
Console.Read();
return 0;


0

该程序在执行完成后即关闭。在这种情况下你return 0;。这是预期的功能。如果要查看输出,则可以在终端中手动运行它,也可以在程序结尾处设置等待时间,以使其保持打开状态几秒钟(使用线程库)。


0

这是C#控制台应用程序上的答案异步吗?

控制台应用中的任何位置永远不会使用await,而是使用theAsyncMethod().GetAwaiter().GetResult();

var result = await HttpClientInstance.SendAsync(message);

变成

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


-3

如果您的程序要求您按Enter键继续,就像您必须输入一个值并继续一样,则添加一个新的double或int并在retunr(0)之前键入write;scanf_s(“%lf”,&variable);


1
这是一个C#问题。
李慧夏

-3

我总是将以下语句添加到控制台应用程序中(如果需要,可以为此创建一个代码段)

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

当您想通过控制台应用程序尝试不同的概念时,这样做会有所帮助。

Ctr + F5键将保留控制台,但您无法调试!我在现实世界中编写的所有控制台应用程序始终是非交互式的,并且由诸如TWS或CA Workstation之类的调度程序触发,并且不需要这样的东西。


-3

为了简化别人在说什么: Console.ReadKey();

这使得程序正在等待用户按下键盘上的普通键

资料来源:我在控制台应用程序的程序中使用它。


-3

您只需调用输入即可解决非常简单的方法。但是,如果按Enter则控制台将再次消失。只需使用此Console.ReadLine();Console.Read();


-4

在返回值0之前添加以下内容:

system("PAUSE");  

这将打印一行以敲键以关闭窗口。它将保持窗口向上,直到您按下Enter键。我让我的学生将其添加到所有程序中。


1
这就是在C ++
贡萨洛加里多

-13

根据我的担心,如果要稳定控制台应用程序的输出,直到输出关闭显示USE,在MainMethod之后贴上标签,然后转到goto标签;程序结束前

在程序中。

例如:

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

    // Snippet of code

    goto label;
}

2
这只会使海报程序继续打印“ Hello,World!”。很多次
DavidPostill 2014年

1
耶稣基督,甚至不知道gotoC#中是否允许声明。
Ch3shire
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.