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

问题描述 投票:145回答:21

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

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

using System;

public class Hello1
{
    public static int Main()
    {
        Console.WriteLine("Hello, World!");
        return 0;
    }
}
c# .net console-application msdn
21个回答
251
投票

这里的问题是他们的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

3
投票

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

    Console.Read(); 
    return 0; 

检查这个Console.Read


3
投票

添加Read方法以显示输出。

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

1
投票

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

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

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/


0
投票

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


0
投票

这是async at console app in 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”,&变量);


-3
投票

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

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

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

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


-3
投票

为了简化别人的说法:使用Console.ReadKey();

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

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


-3
投票

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


62
投票

而不是使用

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

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

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


-4
投票

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

system("PAUSE");  

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


-12
投票

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

在该计划中。

例如:

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

    // Snippet of code

    goto label;
}

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

10
投票

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


6
投票

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


4
投票

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

System.Threading.Thread.Sleep(1000);

请注意Sleep使用毫秒。


4
投票

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


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

3
投票

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

Console.ReadLine();

要么

Console.Read();
© www.soinside.com 2019 - 2024. All rights reserved.