出力が表示された直後にコンソールウィンドウが閉じるのはなぜですか?


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、2018

あなたが外部プロセスによって開始されたコマンドラインプログラムをデバッグしようとしている場合は、この質問を参照してください。stackoverflow.com/a/23334014/3195477
UuDdLrLrSs

回答:


265

ここでの問題は、Hello Worldプログラムが表示され、すぐに終了することです。
何故ですか?

終わったから。コンソールアプリケーションの実行が完了してmainメソッドから戻ると、関連するコンソールウィンドウが自動的に閉じます。これは予想される動作です。

デバッグのために開いたままにする場合は、アプリを終了してウィンドウを閉じる前に、キーを押すのを待つようにコンピューターに指示する必要があります。

このConsole.ReadLine方法は、そのための1つの方法です。この行をコードの最後(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
デバッグなしで実行するとその動作が変わるのはなぜですか?あなたはそれがより正確ではなく、より正確な体験であるべきだと思うでしょう。
カイルデラニー2017

@SameerSinghバイナリにコンパイルされる不要なコードの1行。私は実際にはこのプリプロセッサのアプローチを好みます。
ジョエル

@Joel最近、なぜ私達は一般的にそれを気にする必要があるのでしょうか?
Alex

66

使用する代わりに

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

Ctrl+ を使用してプログラムを実行できますF5(Visual Studio を使用している場合)。その後、Visual Studioは、キーを押すまでコンソールウィンドウを開いたままにします。

注:この方法ではコードをデバッグできません。


こんにちはユーザー。私もVSとC#の一般的な新規ユーザーです。何をしないCtrl + F5だけでかなり違ったことをやるStart異なりますか?
theGreenCabbage 2013年

残念ながら、期待どおりに動作しないことがあります。
MaikoID 2013

2
この問題の原因は、プログラムが停止すると、ウィンドウがターミナルウィンドウを自動的に閉じることです。他のシステムはウィンドウを自動的に開いたままにします。これは、プログラムを実行するはるかに良い方法です。他のコンソールアプリケーションやパイプと組み合わせてプログラムを使用できなくなるため、このようなものにはReadKey、Read、ReadLineを使用しないでください。
リアルタイムの2014

14

デバッグモードで閉じたくない理由は、変数の値などを見たいからだと思います。したがって、メイン関数の閉じる "}"にブレークポイントを挿入するのがおそらく最善です。 。デバッグする必要がない場合は、Ctrl-F5が最適なオプションです。


他のどの回答もこれを示唆していないことに驚いた。質問が作成された後、新しいオプションで回答が遅く追加されることはまれです。
Scott Chamberlain

13

これがために同じ動作をしますCtrlF5F5Mainメソッドの終了直前に配置します。

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()用で、Enter キーが押されるのを待ちます
Chris

6

プログラムの終了を妨げるものがないため、プログラムはすぐに終了します。プログラムが終了しないようにするには、前にブレークポイントを挿入するreturn 0;Console.Read();return 0;に追加します。


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コア2.1コンソールアプリケーションでは機能しません...
user1073075

@ user1073075:これは奇妙です。この機能は他のターゲットでも機能しますか?
Vlad

いいえ。.NETフレームワークコンソールアプリを試してもまだ機能しませんでした。(私は別のマシンにVS2019をインストールし、そこで動作します。多分それはVS17 15.9.4のバグです)
user1073075

2019では、WPFプロジェクトの場合でも機能します:pastebin.com/FpAeV0cW。しかし、あなたは.NETのコア3をインストールする必要があります
ヴラド

5

アプリケーションを開いたままにしたい場合は、そのプロセスを存続させるために何かをする必要があります。以下の例は、プログラムの最後に配置する最も単純な例です。

while (true) ;

ただし、無限に反復する必要があるため、CPUが過負荷になります。

この時点で、System.Windows.Forms.Applicationクラスの使用を選択できます(ただし、System.Windows.Forms参照を追加する必要があります)。

Application.Run();

これはCPUをリークせず、正常に動作します。

System.Windows.Forms参照の追加を避けるために、単純なトリック、いわゆるスピンウェイティングを使用してインポートできSystem.Threadingます。

SpinWait.SpinUntil(() => false);

これも完全に機能し、基本的にはwhile上記のラムダメソッドによって返される否定条件のループで構成されます。なぜこの過負荷な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;。これは予想される機能です。出力を確認したい場合は、ターミナルで手動で実行するか、プログラムの最後に待機を設定して数秒間開いたままにします(スレッドライブラリを使用)。



-3

値を入力して続行する必要がある場合と同様に、プログラムでEnterキーを押して続行する必要がある場合は、新しいdoubleまたはintを追加し、retunr(0)の前にwriteと入力します。scanf_s( "%lf"、&the変数);


1
これはC#の質問です。
Wai Ha Lee

-3

私は常に次のステートメントをコンソールアプリケーションに追加します(必要に応じて、このためのコードスニペットを作成します)。

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

これは、コンソールアプリケーションを使用してさまざまな概念を試したい場合に役立ちます。

Ctr + F5はコンソールを維持しますが、デバッグできません!私が実際に作成したすべてのコンソールアプリケーションは、常に非対話型で、TWSやCAワークステーションなどのスケジューラーによってトリガーされ、このようなものを必要としませんでした。


-3

他の人が言っていることを単純化するには:を使用しConsole.ReadKey();ます。

これにより、プログラムはユーザーがキーボードの通常のキーを押すのを待機します。

出典:コンソールアプリケーションのプログラムで使用しています。


-3

入力を呼び出すだけで非常に簡単な方法で解決できます。ただし、を押すEnterと、コンソールが再び消えます。単にこれを使用するConsole.ReadLine();か、Console.Read();


-4

戻り値0の前に次を追加します。

system("PAUSE");  

これは、ウィンドウを閉じるためのキーを押すための行を出力します。それはあなたがエンターキーを押すまでウィンドウを上に保ちます。生徒にすべてのプログラムに追加してもらいます。


1
ザッツはC ++である
ゴンサーロガリード

-13

私の懸念によると、出力のコンソールアプリケーションを安定させるには、出力が閉じるまでUSE、ラベル:MainMethodの後、およびgotoラベルを表示します。プログラム終了前

プログラム内。

例えば:

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

    // Snippet of code

    goto label;
}

2
これにより、ポスタープログラムが「Hello、World!」を印刷し続けることになります。何度も
DavidPostill 14/07/23

1
イエス・キリストは、gotoC#で許可されている発言さえ知らなかった。
Ch3shire
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.