2009-06-23 6 views
5

큐를 모니터링하는 가장 효율적인 방법은 무엇입니까?큐를 모니터링하는 가장 효율적인 방법

코드의 때라도 조각 자원의 가장 큰 돼지입니다 :

/// <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가에 카운트에 고정하고 있지 않다. 그러나 _MessageQueue.GetMessageFromQueue 구현을 잠급니다. 이 방법이 효과적 이었습니까? 오히려 이벤트를 발생시켜야합니까? 큐가 0부터 0보다 커질 때마다?

답변

5

아마 그 유형으로 스레드 수면을 포함해야합니다. 그렇지 않으면 100 % CPU를 사용하게됩니다. 또는 대기 핸들을 작성하여 대기열에 메시지를 추가 할 때 대기 핸들을 설정할 수 있습니다.

+1

아니오 잔다. 이벤트 또는 신호를 사용하여 적절한 대기/통지를하십시오. –

+0

왜 Mats입니까? 나는 생산자에 대한 통제권을 가지고있다. 항목이 대기열에 추가되면 이벤트를 발생시켜야합니까? 내가 와틀란트를 들여다 보겠다. – 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

관련 문제