2012-06-11 11 views
6

私はこのコードを実行していますが、大部分は何もしていませんが、相当量のCPUを使用しています。条件が満たされるまで操作をブロックする方法はありますか?

while (this.IsListening) 
{ 
    while (this.RecievedMessageBuffer.Count > 0) 
    { 
     lock (this.RecievedMessageBuffer) 
     { 
      this.RecievedMessageBuffer[0].Reconstruct(); 
      this.RecievedMessageBuffer[0].HandleMessage(messageHandler); 
      this.RecievedMessageBuffer.RemoveAt(0); 
     } 
    } 
} 

条件が満たされるまでブロックするにはどうすればよいですか?

+4

'Thread.Sleep()'? –

+0

Thread.Sleep()はUIもブロックします。 –

+4

@RanhiruCoorayいいえ、それはほとんど常に*間違った答えです。 Markによって提案されたWaitHandleのように、この仕事に専念する構造があります。 http://stackoverflow.com/questions/9417260/when-is-it-sensible-to-use-thread-sleep –

答えて

7

.NET 4を使用していると仮定すると、RecievedMessageBufferBlockingCollectionに切り替えることをお勧めします。メッセージを入力するときは、Addというメソッドを呼び出します。メッセージを取得する場合は、TakeまたはTryTakeのメソッドを呼び出します。テイクは、オリジナルの例のようにCPUを焼くことなく、メッセージが利用可能になるまで読み取りスレッドをブロックします。

// Somewhere else 
BlockingCollection<SomethingLikeAMessage> RecievedMessageBuffer = new BlockingCollection<SomethingLikeAMessage>(); 


// Something like this where your example was 
while (this.IsListening) 
{ 
    SomethingLikeAMessage message; 
    if (RecievedMessageBuffer.TryTake(out message, 5000); 
    { 
     message.Reconstruct(); 
     message.HandleMessage(messageHandler); 
    } 
} 
+1

ありがとうございました!それは私が必要とするものに最適です!私はSyncronizedCollection <>を使用していましたが、BlockingCollection <>もスレッドセーフであるため、これは私がやっていることに最適です!すべてが今、幻想的に滑らかに走っています! – MJLaukala

9

WaitHandleを使用してください。

WaitHandle waitHandle = new AutoResetEvent(); 

// In your thread. 
waitHandle.WaitOne(); 

// In another thread signal that the condition is met. 
waitHandle.Set(); 

また、読み込む新しいデータがある場合にイベントを発生させるために、クラスのインターフェイスを変更することも考えられます。次に、コードをイベントハンドラの中に置くことができます。

+0

私はWaitHandlesでいくつかのテストを行う必要があります。今日までに彼らについては決して知らなかった。数週間前までにマルチスレッドで深刻なことはありませんでした。 – MJLaukala

+0

'WaitHandle'を' Set() 'メソッドで使うことができませんでした。代わりに少なくとも 'EventWaitHandle'があるはずです。 – Gucu112

2

上記のコード行と特にAutoResetEventは、バージョン3.5で使用できます。上のような単純なコードでは、いくつかの小さな修正を加えれば、それがうまく動作し、基盤APIに近いので、非常に効果的です。修正は、

である必要があります。AutoResetEvent waitHandle = new AutoResetEvent(false); 引数がfalseのコンストラクタは、AutoResetEvenがリセットされないため(false)WaitOne()を待機させます。インターフェイスWaitHandleを使用する利点はあまりないので、代わりにAutoResetEventを使用します。この場合、メソッドSetとWaitOneは非常に冗長です。最も重要なのは、コンストラクタの引数で、falseでなければなりません。

関連する問題