一部のサービスを別のスレッドで起動するコンソールアプリケーションを検討してください。ユーザーがCtrl + Cを押してシャットダウンするのを待つだけです。
これを行うためのより良い方法は次のうちどれですか?
static ManualResetEvent _quitEvent = new ManualResetEvent(false);
static void Main() {
Console.CancelKeyPress += (sender, eArgs) => {
_quitEvent.Set();
eArgs.Cancel = true;
};
// kick off asynchronous stuff
_quitEvent.WaitOne();
// cleanup/shutdown and quit
}
または、これはThread.Sleep(1)を使用して:
static bool _quitFlag = false;
static void Main() {
Console.CancelKeyPress += delegate {
_quitFlag = true;
};
// kick off asynchronous stuff
while (!_quitFlag) {
Thread.Sleep(1);
}
// cleanup/shutdown and quit
}
特にコードに変数の再チェックを強制する場合は、Whileループの使用を常に禁止する必要があります。 CPUリソースを浪費し、プログラムの速度を低下させます。
私は間違いなく最初のものを言うでしょう。
または、より単純な解決策は次のとおりです。
Console.ReadLine();
あなたはそれを行うことができます(そしてCancelKeyPress
イベントハンドラを削除します):
while(!_quitFlag)
{
var keyInfo = Console.ReadKey();
_quitFlag = keyInfo.Key == ConsoleKey.C
&& keyInfo.Modifiers == ConsoleModifiers.Control;
}
それが良いかどうかはわかりませんが、ループでThread.Sleep
を呼び出すという考えは好きではありません。ユーザー入力をブロックする方がクリーンだと思います。
Application.Runを使用することを好みます
static void Main(string[] args) {
//Do your stuff here
System.Windows.Forms.Application.Run();
//Cleanup/Before Quit
}
ドキュメントから:
フォームなしで、現在のスレッドで標準アプリケーションメッセージループの実行を開始します。
必要以上に難しくしているようです。停止するように信号を送った後、スレッドをただJoin
しないのはなぜですか?
class Program
{
static void Main(string[] args)
{
Worker worker = new Worker();
Thread t = new Thread(worker.DoWork);
t.IsBackground = true;
t.Start();
while (true)
{
var keyInfo = Console.ReadKey();
if (keyInfo.Key == ConsoleKey.C && keyInfo.Modifiers == ConsoleModifiers.Control)
{
worker.KeepGoing = false;
break;
}
}
t.Join();
}
}
class Worker
{
public bool KeepGoing { get; set; }
public Worker()
{
KeepGoing = true;
}
public void DoWork()
{
while (KeepGoing)
{
Console.WriteLine("Ding");
Thread.Sleep(200);
}
}
}
最初の2つの方が良い
_quitEvent.WaitOne();
2番目のスレッドでは、スレッドが1ミリ秒ごとにウェイクアップするため、OS割り込みが発生しますが、これは高価です
キャンセルトークンに基づいてスレッド/プログラムをブロックすることもできます。
token.WaitHandle.WaitOne();
トークンがキャンセルされると、WaitHandleが通知されます。
Microsoft.Azure.WebJobs.JobHostで使用されるこの手法を見てきました。トークンはWebJobsShutdownWatcher(ジョブを終了するFile Watcher)のキャンセルトークンソースから取得されます。
これにより、プログラムをいつ終了できるかをある程度制御できます。
Windowsサービスをプログラミングする場合と同じように行う必要があります。デリゲートを使用する代わりに、whileステートメントを使用することはありません。通常、WaitOne()は、スレッドの破棄を待機しているときに使用されます-Thread.Sleep()-表示されません-そのイベントを使用してSystem.Timers.Timerを使用してシャットダウンイベントを確認することを考えましたか?