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

时间:2012-01-15 08:06:25

标签: c# .net console-application msdn

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

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

using System;

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

22 个答案:

答案 0 :(得分:249)

  

这里的问题是他们的Hello World计划出现然后会立即关闭   那是为什么?

因为它已经完成。当控制台应用程序完成执行并从main方法返回时,关联的控制台窗口会自动关闭。这是预期的行为。

如果您想将其打开以进行调试,则需要指示计算机在结束应用程序并关闭窗口之前等待按键操作。

Console.ReadLine method是这样做的一种方式。将此行添加到代码末尾(就在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

答案 1 :(得分:59)

而不是使用

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

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

注意:您无法使用此方法调试代码。

答案 2 :(得分:13)

Ctrl F5 F5 的行为相同。 紧接在Main方法结束之前放置。

using System.Diagnostics;

private static void Main(string[] args) {

  DoWork();

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

答案 3 :(得分:9)

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

答案 4 :(得分:6)

程序立即关闭,因为没有什么能阻止它关闭。在return 0;插入一个断点或在Console.Read();之前添加return 0;以阻止程序关闭。

答案 5 :(得分:4)

或者,您可以使用以下代码延迟结束:

System.Threading.Thread.Sleep(1000);

注意Sleep使用的是毫秒。

答案 6 :(得分:4)

另一种方法是在从Main方法

返回之前使用Debugger.Break()

答案 7 :(得分:4)

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

while (true) ;

然而,它会导致CPU过载,因为它被迫无限迭代。

此时,您可以选择使用System.Windows.Forms.Application类(但需要添加System.Windows.Forms引用):

Application.Run();

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

为了避免添加System.Windows.Forms引用,您可以使用一个简单的技巧,即所谓的旋转等待,导入System.Threading

SpinWait.SpinUntil(() => false);

这也很有效,它主要包含一个while迭代器,它具有由上述lambda方法返回的否定条件。为什么这不会超载CPU?您可以查看源代码here;无论如何,它基本上等待处理器的一些循环以保持指令运行。

您还可以选择创建一个消息循环器,它会在传递到下一次迭代之前查看待处理的消息并处理每个消息:

[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();

更好的是,你可以通过用while调用替换SpinWait.SpinUntil迭代器来混合后两个解决方案:

SpinWait.SpinUntil(ProcessMessageOnce);

答案 8 :(得分:3)

代码完成,继续你需要添加:

Console.ReadLine();

Console.Read();

答案 9 :(得分:3)

添加Read方法以显示输出。

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

答案 10 :(得分:3)

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

    Console.Read(); 
    return 0; 

检查此Console.Read

答案 11 :(得分:1)

我参加聚会有点晚了,但是:在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/

答案 12 :(得分:0)

工具 -> 选项 -> 调试 -> 常规 -> 自动关闭控制台(第 5 个最后一个选项)

勾选并关闭

这适用于所有项目。

答案 13 :(得分:0)

程序在执行完成后立即关闭。在这种情况下,return 0;。这是预期的功能。如果你想看到输出,那么要么手动在终端中运行它,要么在程序结束时设置一个等待,以使它保持打开几秒钟(使用线程库)。

答案 14 :(得分:0)

这是一种不涉及Console的方法:

var endlessTask = new TaskCompletionSource<bool>().Task;
endlessTask.Wait();

答案 15 :(得分:0)

这是答案async at console app in C#?

在控制台应用程序中的任何地方,从不使用await,而是使用theAsyncMethod().GetAwaiter().GetResult();

示例

var result = await HttpClientInstance.SendAsync(message);

成为

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

答案 16 :(得分:-3)

只需调用输入就可以非常简单地解决它。但是,如果按Enter,控制台将再次消失。只需使用此Console.ReadLine();Console.Read();

即可

答案 17 :(得分:-3)

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

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

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

Ctr + F5 会使控制台停留但您无法调试!我在realworld中编写的所有控制台应用程序始终是非交互式的,并且由诸如TWS或CA Workstation之类的调度程序触发,并且不需要这样的内容。

答案 18 :(得分:-3)

简化其他人所说的话: 使用Console.ReadKey();

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

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

答案 19 :(得分:-3)

如果您的程序要求您按Enter继续喜欢 你必须输入一个值并继续, 然后添加一个新的double或int 并在retunr(0)之前输入write; scanf_s(“%lf”,&amp;变量);

答案 20 :(得分:-4)

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

system("PAUSE");  

这会打印一条线来点击一个键来关闭窗口。它将保持窗口直到你按下回车键。我让我的学生将它添加到他们所有的课程中。

答案 21 :(得分:-12)

根据我的关注,如果我们要稳定控制台应用的输出,直到输出结束显示USE,标签:在MainMethod和goto标签之后;在节目结束之前

在计划中。

例如:

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

    // Snippet of code

    goto label;
}