イベントをリッスンしながら常に開いておきたいコンソール アプリケーションがあります。私がテストThread.Sleep(Timeout.Infinite);
しwhile (true) { }
たところ、両方とも、コンソール アプリケーションを開いたままにしてイベントを発生させることができました。他のものよりも使用する必要があるものはありますか? スレッドがスリープしている場合、クラスのスコープで宣言された静的コレクションを変更するなど、してはいけないことはありますか?
6 に答える
ManualResetEvent
(またはその他WaitHandle
)を使用し、ManualResetEvent.WaitOneを呼び出すことをお勧めします。
これは、必要に応じて (イベントを呼び出すことによって) 無限の「ブロック」から抜け出すためのクリーンな方法を提供することを除いて、永久にスリープするのと同様の効果があります。Set()
を使用while(true)
すると CPU サイクルが消費されるため、絶対に避けるべきものです。
クラスのスコープで宣言された静的コレクションを変更するなど、してはいけないことはありますか?
一般的に、いいえ。スレッドがブロックされるため、共有データを使用しても同期の問題は発生しません (適切な同期コンテキストを持つスレッドで使用する必要があるユーザー インターフェイス要素など、コレクション内のアイテムに特定の要件がない場合)。 .)
コールだと思います
while (true) { ... }
スレッドは決して停止しないため、計算集約的です。
Thread.Sleep(Timeout.Infinite);
OSネイティブスケジューラの助けを借りて、実際にスレッドをスリープ状態にします。そして、スレッドが実際に停止するので、計算負荷が少ないと思います。
とは異なりwhile(true)...
、Thread.Sleep
CPU サイクルを使用しないため、この意味で、スリープはより効率的です。一般に、スピンロックの外でBusy Waitingを使用することは強くお勧めしません。
スレッドがスリープしている場合、してはいけないことはありますか?
へのエントリ時にスレッドがブロックされるため、スレッドThread.Sleep
のリソースに対して実行したいことはすべて公正なゲームです。
はい、
よりスマートな方法でwhile(true)
動作しながら CPU を消費します。関数は現在の実行コンテキストをスリープ状態にします。これは、syscall を呼び出してカーネル スリープ関数を呼び出すことによって行われます。カーネル スリープ関数は、アトミックに
(a) ウェイクアップ タイマーを設定します
(b) 現在のプロセスをスリープ状態としてマークします
(c) ウェイクアップ タイマーが起動するか、割り込みが発生するまで待機します sleep()
sleep()
を呼び出すsleep()
と、CPU は他の作業を行うことができます。
sleep()
これが便利な理由の 1 つです。
便利なリンク -スリープを使用するときは注意してください
Thread.Sleep メソッドを呼び出すと、現在のスレッドは、メソッドに渡されたミリ秒数または時間間隔の間、ただちにブロックされ、残りのタイム スライスは別のスレッドに渡されます。