2009-06-23 15 views
5

キューを監視する最も効率的な方法は何ですか。キューを最も効率的に監視する方法

コードのfollwoing作品は、リソースの最大の独り占めです:

/// <summary> 
/// Starts the service. 
/// </summary> 
private void StartService() 
{ 
    while (true) 
    { 
     //the check on count is not thread safe 
     while (_MessageQueue.Count > 0) 
     { 
      Common.IMessage message; 
      // the call to GetMessageFromQueue is thread safe 
      if (_MessageQueue.GetMessageFromQueue(out message) == true) 
      { 
       if (message.RoutingInfo == Devices.Common.MessageRoutingInfo.ToDevice) 
       { 
        _Port.SerialPort.WriteLine(message.Message); 
       } 
       if (message.RoutingInfo == Devices.Common.MessageRoutingInfo.FromDevice) 
       { 
        OnDeviceMessageReceived(new Common.DeviceMessageArgs(message.Message)); 
       } 
      } 
     } 
    } 
} 

サービス開始は、バックグラウンドスレッド上で動作する、_MessageQueue.Countへの呼び出しはスレッドセーフではありません、私は、メッセージキューにカウントにロックしていないです。しかし、私は_MessageQueue.GetMessageFromQueueの実装をロックします。 これは効率的な方法ですか?私はむしろイベントを発生させるべきですか?キューが0から0以上になるたびに?

答えて

5

おそらく、そのメソッドには何らかのタイプのスレッドスリープが含まれているはずです。それ以外の場合は、100%CPUを使用します。または、待機ハンドルを作成し、メッセージをキューに追加するときに設定することもできます。

+1

ませんが眠ります。適切な待機/通知を行うには、イベントまたは信号を使用します。 –

+0

なぜマットですか?私はプロデューサーを支配している。アイテムがキューに追加されたときにイベントを発生させるべきですか?私はワイタンダルを調べます。 – AndyMM

+0

+1。例については私の答えを見てください。 – dtb

1

_MessageQueueはコードからのみ使用されていますか?メッセージが使用可能になるまで

public class BlockingMessageQueue { 
    private readonly MyMessageQueue queue; 
    private readonly Semaphore signal; 

    public BlockingMessageQueue(MyMessageQueue queue) { 
    this.queue = queue; 
    this.signal = new Semaphore(0, int.MaxValue); 
    } 

    public void Enqueue(IMessage message) { 
    lock (this.queue) { 
     this.queue.Send(message); 
    } 
    this.signal.Release(); 
    } 

    public IMessage Dequeue() { 
    this.signal.WaitOne(); 
    IMessage message; 
    lock (this.queue) { 
     var success = this.queue.GetMessageFromQueue(out message); 
     Debug.Assert(success); 
    } 
    return message; 
    } 
} 

Dequeueがブロックされるので、メッセージがない場合は無駄なサイクルが存在しない。そして、あなたはこのようなクラスでそれを包むことができます。

使用例:あなたがプロデューサーを超える一切のコントロールを持っていない場合を除き

var queue = new BlockingMessageQueue(_MessageQueue); 

while (true) { 
    var message = queue.Dequeue(); 

    if (message.RoutingInfo == Devices.Common.MessageRoutingInfo.ToDevice) 
    { 
    _Port.SerialPort.WriteLine(message.Message); 
    } 
    else if (message.RoutingInfo == Devices.Common.MessageRoutingInfo.FromDevice) 
    { 
    OnDeviceMessageReceived(new Common.DeviceMessageArgs(message.Message)); 
    } 
} 
+0

ありがとう、私は間違いなくこれを行ってくれます。私はそれがどのように実行されるかをお知らせします。ありがとう – AndyMM

関連する問題