私はそれ自身のスレッドで実行され、ブロックせずに起動/停止することができるプロセスを持っています。これは最終的にWindowsサービスに入りますが、コンソールアプリケーションでこれを設定しています。これは完全に完了するまでです。whileループの代わりにセマフォを使用する。これは良いか悪いですか?
Start()を呼び出した後、Ctrl-Cを押すまでメインプログラムスレッドをブロックします。私は、これが動作することを知っている:
public static void Main(string[] args)
{
bool keepGoing = true;
var service = new Service();
System.Console.TreatControlCAsInput = false;
System.Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e)
{
e.Cancel = true;
service.Stop();
keepGoing = false; // Break the while loop below
};
service.Start();
while(keepGoing)
{
Thread.Sleep(100); // 100 is arbitrary
}
}
しかし、私はフラグと、任意の睡眠値が面倒見つけます。私はCPUコストがwhileループでは実質的に0であることを知っていますが、Ctrl-Cハンドラが終了するとすぐに「ハード」ブロックをリリースします。私は匿名のCtrl-Cハンドラが完了するまでセマフォを使って以下を考案しました:
public static void Main(string[] args)
{
var service = new Service();
var s = new Semaphore(1, 1);
System.Console.TreatControlCAsInput = false;
System.Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e)
{
e.Cancel = true;
service.Stop();
s.Release(); // This will allow the program to conclude below
};
service.Start();
s.WaitOne(); // This will not block
s.WaitOne(); // This will block w/o CPU usage until the sempahore is released
}
これは悪い設計ですか?それは過労ですか?それは危険ですか?
EDIT:
次のように私はまたAppDomain.CurrentDomain.UnhandledExceptionをフックアップ:
AppDomain.CurrentDomain.UnhandledException += delegate {
service.Stop();
s.Release();
};
EDIT 2位:
を私はそれがことが重要であることに注意してくださいStop()
メソッドは終了時に呼び出されます。 @Adam Ralphは、ハイブリッドコンソール/サービスの完全なパターンを持っていますが、Qに答えるときにはこの情報を持っていませんでした。
whileループを避けることができれば、追求する価値があると言います。 – ChaosPandion
プロトタイプ作成では、後者の方がはるかに改善されています。プロダクションアプリケーションでは、私は全体の "CTRL + C"ブレークアイデアを避けるでしょう。シグナルを使用してスレッドを強制終了します。シグナルが 'Set()'のやり方は、他の層に依存します。サービスを設計するときは、これを覚えておいてください。 'Set()'を呼び出すことができるメソッドのような手段を追加してください。 –
@ P.Brian。Mackey:これはプロダクションアプリケーションではありませんが、*の場合は、非対話型のコンソールアプリケーションでCtrl-Cをうまく処理することは賢明ではないでしょうか?そのままでは、Ctrl + Cは終了する前にクリーンアップする機会を持たずに単にプログラムをシャットダウンします。最終的に、私は単に、while(flag)Thread.Sleep(...)オプションに対するセマフォー・ソリューションかどうか疑問に思っていました。 –