2009-06-23 10 views
5

Quel est le moyen le plus efficace de surveiller une file d'attente?Méthode la plus efficace pour surveiller une file d'attente

La pièce follwoing de code est le plus grand porc des ressources:

/// <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)); 
       } 
      } 
     } 
    } 
} 

Démarrer le service fonctionne sur un fil d'arrière-plan, l'appel à _MessageQueue.Count est pas sûre, je ne suis pas de verrouillage sur le nombre dans MessageQueue. Je bloque cependant l'implémentation de _MessageQueue.GetMessageFromQueue. Est-ce que le chemin que j'ai parcouru à ce sujet est efficace? Dois-je plutôt élever un événement Chaque fois que la file d'attente passe d'un nombre de 0 à plus de zéro?

Répondre

5

Vous devriez probablement inclure un certain type de thread de sommeil dans cette méthode, sinon il va utiliser 100% CPU. Vous pouvez également créer un handle d'attente et le définir lorsque vous ajoutez un message à la file d'attente.

+1

Non dort, sauf si vous avez aucun contrôle sur le producteur. Utilisez des événements ou des signaux pour faire des attentes/notifications appropriées. –

+0

Pourquoi Mats? J'ai le contrôle sur le producteur. Devrais-je déclencher un événement lorsqu'un élément est ajouté à la file d'attente? Je vais regarder dans waithandle. – AndyMM

+0

+1. Voir ma réponse pour un exemple. – dtb

1

Est-ce que _MessageQueue n'est utilisé qu'à partir de votre code? Ensuite, vous pouvez l'envelopper dans une classe comme ceci:

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 bloquera jusqu'à ce qu'un message est disponible, donc il n'y a pas de cycles gaspillés si aucun message est disponible.

Exemple d'utilisation:

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

Merci beaucoup, je vais certainement essayer. Je vous ferai savoir comment cela fonctionne. Merci – AndyMM

Questions connexes