イベントをリッスンしている間、常に開いておきたいコンソールアプリケーションがあります。私はThread.Sleep(Timeout.Infinite);
とwhile (true) { }
をテストしましたが、どちらもコンソールアプリケーションを開いたままイベントを発生させることができます。他に使用すべきものはありますか?スレッドがスリープ状態の場合、クラスのスコープで宣言された静的コレクションの変更など、私がしてはいけないことはありますか?
ManualResetEvent
(またはその他のWaitHandle
)を使用して、 ManualResetEvent.WaitOne を呼び出すことをお勧めします。
これは、永久にスリープするのと同様の効果がありますが、必要なときに無限ブロックからexitへのクリーンな方法を提供します(- Set()
イベントの場合)。
while(true)
を使用するとCPUサイクルが消費されるため、これは間違いなく避けてください。
クラスのスコープで宣言された静的コレクションを変更するなど、私がしてはいけないことはありますか?
一般的には違います。スレッドがブロックされるため、共有データの使用に同期の問題はありません(コレクション内のアイテムに、適切な同期コンテキストを持つスレッドで使用する必要があるユーザーインターフェイス要素などの特定の要件がない場合)。 。)
while(true)...
とは異なり、Thread.Sleep
はCPUサイクルを使用しないため、この意味で、スリープはより効率的です。一般に、 spinlocks の外で Busy Waiting を使用することは強くお勧めしません。
スレッドがスリープしている場合、私がしてはいけないことはありますか?
Thread.Sleep
へのエントリ時にスレッドがブロックされるため、そのリソースに対して実行したいことは何でも公正なゲームです。
電話だと思う
while (true) { ... }
スレッドは停止しないため、計算集約的であり、
Thread.Sleep(Timeout.Infinite);
実際には、OSネイティブスケジューラの助けを借りてスレッドをスリープ状態にします。そして、スレッドは実際に停止するので、計算の負荷が軽減されると思います。
はい、while(true)
はCPUを消費しますが、sleep()
はよりスマートに機能します:sleep()
関数は、現在の実行コンテキストをスリープ状態にします。これは、syscallを呼び出して、カーネルスリープ関数を呼び出し、
(a)ウェイクアップタイマーを設定する
(b)現在のプロセスをスリープ状態としてマークします
(c)ウェイクアップタイマーが起動するか、割り込みが発生するまで待機します
sleep()
を呼び出すと、CPUは他の処理を実行できます。
これが、sleep()
が役立つ理由の1つです。
便利なリンク- スリープを使用するときは注意してください
Thread.Sleepメソッドを呼び出すと、現在のスレッドがミリ秒数またはメソッドに渡された時間間隔で直ちにブロックされ、残りのタイムスライスが別のスレッドに渡されます。
https://msdn.Microsoft.com/en-us/library/tttdef8x(v = vs.110).aspx
C#7.1以降、Mainメソッドを非同期にすることができます。つまり、busy-waitやthread-locking sleepingを使用する代わりに、MainメソッドをTaskとして非同期に中断できます。このように実行されたスレッドMainはロックされません。また、Cts.Cancel();
を使用すると、メインタスクを簡単に解放してアプリケーションを終了できます。
readonly CancellationTokenSource Cts = new CancellationTokenSource();
static async Task Main(string[] args)
{
/* your code here */
await Task.Delay(Timeout.Infinite, Cts.Token);
}