MSDNのガイドに従ってC#を勉強しています。
さて、私は例1( here はMSDNへのリンクです)を試したところ、問題:コンソールウィンドウが出力を表示したらすぐに閉じるのはなぜですか?
using System;
public class Hello1
{
public static int Main()
{
Console.WriteLine("Hello, World!");
return 0;
}
}
ここでの問題は、彼らのハローワールドプログラムが現れていて、それがすぐに閉じるということです。
何故ですか?
終了したためです。コンソールアプリケーションの実行が完了してmain
メソッドから戻ると、関連するコンソールウィンドウは自動的に閉じます。これは予想される動作です。
デバッグ目的で開いたままにしておきたい場合は、アプリを終了してウィンドウを閉じる前に、キーを押すのを待つようにコンピュータに指示する必要があります。
Console.ReadLine
メソッド がその1つの方法です。この行をコードの末尾(return
ステートメントの直前)に追加すると、アプリケーションは終了する前にキーを押すのを待ちます。
あるいは、デバッガを接続せずにアプリケーションを起動することもできます。 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
使用する代わりに
Console.Readline()
Console.Read()
Console.ReadKey()
あなたが使用してあなたのプログラムを実行することができます Ctrl+F5 (あなたがVisual Studioにいるならば)。その後、キーを押すまで、Visual Studioはコンソールウィンドウを開いたままにします。
注:この方法ではコードをデバッグできません。
これは同じ動作をします。 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();
}
}
デバッグモードで閉じたくないのは、変数の値などを調べたいからです。メイン関数の最後の "}"にブレークポイントを挿入することをお勧めします。 。デバッグする必要がない場合は、Ctrl-F5が最善の選択肢です。
閉じるのを止めるものは何もないので、プログラムはすぐに閉じます。プログラムが閉じないようにするには、return 0;
にブレークポイントを挿入するか、return 0;
の前にConsole.Read();
を追加します。
あるいは、次のコードを使用して終了を遅らせることができます。
System.Threading.Thread.Sleep(1000);
Sleep
がミリ秒を使用していることに注意してください。
アプリケーションを開いたままにしたい場合は、そのプロセスを有効に保つために何かをする必要があります。以下はプログラムの最後に置く最も簡単な例です。
while (true) ;
ただし、無限に繰り返すことを余儀なくされるため、CPUが過負荷になります。
この時点で、System.Windows.Forms.Application
クラスを使用することを選択できます(ただし、System.Windows.Forms
参照を追加する必要があります)。
Application.Run();
これはCPUをリークすることはなく、正常に動作します。
System.Windows.Forms
参照を追加しないようにするために、単純なトリック、いわゆるスピン待機を使用して、System.Threading
をインポートすることができます。
SpinWait.SpinUntil(() => false);
これも完璧に機能し、主に上記のラムダメソッドによって返される否定条件を持つwhile
イテレータで構成されています。なぜこの過負荷の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();
さらに良いことに、while
イテレータをSpinWait.SpinUntil
呼び出しに置き換えることで、後者の2つの解決策を組み合わせることができます。
SpinWait.SpinUntil(ProcessMessageOnce);
別の方法は、Mainメソッドから戻る前にDebugger.Break()
を使うことです
コードは完成しました。続行するには、これを追加する必要があります。
Console.ReadLine();
または
Console.Read();
出力を表示するためのRead
メソッドを追加します。
Console.WriteLine("Hello, World!");
Console.Read();
return 0;
Console.Read()を使用してください。プログラムが終了しないようにするには、returnステートメントの前にConsole.Read();
コードを追加してください。そうしないと、到達不能コードになります。
Console.Read();
return 0;
これを確認してください Console.Read
私はパーティーに少し遅れていますが、.NET Coreプロジェクト用のVisual Studio 2019では、コンソールはデフォルトで自動的に閉じません。メニューの[ツール]→[オプション]→[デバッグ]→[全般]→[デバッグが停止したら自動的にコンソールを閉じる]を選択して、動作を設定できます。コンソールウィンドウが自動的に閉じられる場合は、上記の設定が設定されていないかどうかを確認してください。
同じことが.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/
Console
を使わずにこれを行う方法は次のとおりです。
var endlessTask = new TaskCompletionSource<bool>().Task;
endlessTask.Wait();
実行が完了するとすぐにプログラムは終了します。この場合はreturn 0;
とします。これは期待される機能です。出力を見たい場合は、端末で手動で実行するか、プログラムの最後に待機を設定して(スレッドライブラリを使用して)数秒間開いたままになるようにします。
これが答えです C#のコンソールアプリで非同期?
コンソールアプリ内のどこでもawait
を使用することはなく、代わりにtheAsyncMethod().GetAwaiter().GetResult();
を使用します
例
var result = await HttpClientInstance.SendAsync(message);
になる
var result = HttpClientInstance.SendAsync(message).GetAwaiter().GetResult();