2017-05-30 2 views
0

J'essaie de trouver un moyen de fil en toute sécurité et de performance défaire sage un TryDequeue sur un ConcurrentQueueC# Annuler une TryDequeue sur ConcurrentQueue

Ma solution actuelle au problème est:

lock(_queue) { 
    _queue = new ConcurrentQueue<IItem>(_queue.Reverse()); 
    _queue.Enqueue(item); 
    _queue = new ConcurrentQueue<IItem>(_queue.Reverse()); 
} 

Mais Je ne sais pas si c'est la meilleure façon de le faire, parce que je le verrouille manuellement. Mais je dois être sûr que la file d'attente ne sera pas modifiée dans un autre thread pendant ce processus.

La raison de devoir faire ceci (je pense) est que je fais un TryPeek, fais un contrôle sur l'article retourné, s'il répond à un critère, je fais une TryDequeue, et refais la vérification, si elle échoue la deuxième fois que je veux faire un retour en arrière. Est-ce que ça a du sens?

+2

Cela ressemble beaucoup à un problème X-Y. En toute probabilité, vous utilisez le mauvais outil pour le travail. – xxbbcc

+0

@TimSchmelter Même si je reconstruis complètement l'objet comme dans l'exemple? –

+6

En fait, votre 'lock' n'a pas d'effet puisque vous remplacez la référence verrouillée. –

Répondre

1

Si vous devez verrouiller l'accès à la file d'attente pendant que vous la lisez, le but du ConcurrentQueue est annulé. Vous pourriez aussi bien écrire votre propre enveloppe autour d'un Queue<T> normal.

public class UndoableQueue<T> // I shouldn't be allowed to name anything, ever. 
{ 
    private readonly Queue<T> _queue = new Queue<T>(); 
    private readonly object _lock = new object(); 

    public void Enqueue(T item) 
    { 
     lock (_lock) 
     { 
      _queue.Enqueue(item); 
     } 
    } 

    public bool TryDequeue(Func<T, bool> verify, out T dequeued) 
    { 
     lock (_lock) 
     { 
      if (!_queue.Any()) 
      { 
       dequeued = default(T); 
       return false; 
      } 
      if (verify(_queue.Peek())) 
      { 
       dequeued = _queue.Dequeue(); 
       return true; 
      } 
      dequeued = default(T); 
      return false; 
     } 
    } 
} 

TryDequeue prend une fonction qui détermine si oui ou non pour retourner l'article. Cela fonctionne comme TryDequeue sur ConcurrentQueue sauf qu'il renvoie une valeur s'il y a un élément dans la file d'attente et la fonction renvoie true pour cet élément.

+0

Cela pourrait fonctionner! THX –