2010-04-22 4 views
2

Existe-t-il un équivalent de Monitor.Pulse et Monitor.Wait que je peux utiliser conjointement avec un ReaderWriterLockSlim?ReaderWriterLockSlim et Pulse/Wait

J'ai une classe où j'ai encapsulé l'accès multi-thread à une file d'attente sous-jacente. Pour mettre en file d'attente quelque chose, j'obtiens un verrou qui protège la file d'attente sous-jacente (et quelques autres objets) puis ajoute l'objet et Monitor.Pulse l'objet verrouillé pour signaler que quelque chose a été ajouté à la file d'attente. À l'autre extrémité de la file d'attente, j'ai un seul thread d'arrière-plan qui traite les messages en continu lorsqu'ils arrivent dans la file d'attente. Il utilise Monitor.Wait lorsqu'il n'y a aucun élément dans la file d'attente, pour éviter une interrogation inutile. (Je considère cela comme un bon design, mais les flammes (raison) sont les bienvenus si elles me aider à apprendre autrement.)

private void DequeueForProcessing(object state) 
{ 
    while (true) 
    { 
     ITask task; 
     lock (mutex) 
     { 
      while (underlying.Count == 0) 
      { 
       Monitor.Wait(mutex); 
      } 
      task = underlying.Dequeue(); 
     } 
     Process(task); 
    } 
}

Comme plus d'opérations sont ajoutées à cette classe (nécessitant un accès en lecture seule à la serrure sous-jacent protégé), quelqu'un a suggéré d'utiliser ReaderWriterLockSlim. Je n'ai jamais utilisé la classe auparavant, et en supposant qu'elle puisse offrir des avantages de performance, je ne suis pas contre, mais seulement si je peux garder le design Pulse/Wait.

+1

Pour les commentaires ... Je ne supposerais pas personnellement que se réveiller de «Wait» signifie «il y a des données»; Je frapperais 'continuer;' et vérifier encore. Cette approche facilite l'ajout d'une installation d'arrêt/de vidange plus tard. Vous pourriez également vouloir seulement 'Pulse' si vous avez ajouté à une file d'attente précédemment vide; sinon, rien n'attend. –

+0

J'aime l'idée de faire l'impulsion seulement après avoir ajouté un seul élément à la file d'attente. Cependant, j'ai un tas d'autres doutes sur mon code (aussi bien que je devrais, c'est multi-threaded), ainsi que l'efficacité de compter les éléments dans la file d'attente et de comparer cette valeur avec 0 (j'espère que ça ne marche pas une liste liée pour faire le comptage.) Je suppose que je devrais vraiment appeler PulseAll dans le cas où c'est un autre thread d'auteur qui reçoit le pouls unique. – Jono

+0

Je serais d'accord avec le 'PulseAll'. Re the 'Count', voir documentation: http://msdn.microsoft.com/en-us/library/fy0wwyz4.aspx" Récupérer la valeur de cette propriété est une opération O (1). "; ce qui signifie: non, il ne fait pas cela - il connaît le «Count» séparément. –

Répondre

0

Après avoir joué un peu (et après avoir accepté le défi de Mark (Je suis d'accord, mon changement est pas exactement de base)) je suis venu avec cette combinaison:

ReaderWriterLockSlim rwls; 
AutoResetEvent are;
public void Enqueue(ITask task) { 
    rwls.EnterWriteLock(); 
    try { 
     underlying.Enqueue(task); 
     if (underlying.Count == 1) { 
      are.Set(); 
     } 
    } finally { 
     rwls.ExitWriteLock(); 
    } 
}
private void DequeueForProcessing(object state) { 
    while (true) { 
     ITask task; 
     rwls.EnterWriteLock(); 
     try { 
      while (underlying.Count == 0) { 
       rwls.ExitWriteLock(); 
       are.WaitOne(); 
       rwls.EnterWriteLock(); 
      } 
      task = underlying.Dequeue(); 
     } finally { 
      rwls.ExitWriteLock(); 
     } 
     Process(task); 
    } 
}

À ma œil non entraîné, il semble correspondre à la facture (même si c'est un peu plus laids, pour être sûr,) et ce n'est pas trop différent de la version originale.

1

Non, fondamentalement. Il est optimisé pour fournir des scénarios spécifiques/communs. Si vous sortez de ces scénarios, cela ne fonctionnera pas. Si vous avez besoin de Pulse etc, utilisez plutôt Monitor.

+0

Existe-t-il d'autres mécanismes .NET intégrés qui peuvent remettre le thread en cours dans la file d'attente pour un verrou ou est-ce que le moniteur fait? – Jono

+0

@Jono - 'Monitor.Wait' –

Questions connexes