2017-05-30 98 views
0

我試圖找出一種方法來安全線程與性能明智撤消TryDequeue上ConcurrentQueueC#撤消TryDequeue上ConcurrentQueue

我目前的解決問題的辦法是:

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

但我不知道這是否是最好的方法,因爲我手動鎖定它。但是我需要確保在這個過程中隊列不會在另一個線程中被更改。

必須這樣做(我認爲)的原因是我做了一個TryPeek,檢查返回的項目,如果它滿足條件,我做一個TryDequeue,並再次執行檢查,如果失敗第二次我想回滾。這有意義嗎?

+2

這聽起來很像X-Y問題。在所有可能的情況下,你使用錯誤的工具來完成這項工作。 – xxbbcc

+0

@TimSchmelter即使我完全重建像在這個例子中的對象? –

+6

其實你的'lock'沒有效果,因爲你正在替換被鎖定的參考。 –

回答

1

如果您需要在讀取隊列時鎖定對隊列的訪問權限,則ConcurrentQueue的用途將被取消。你可以在正常的Queue<T>周圍寫下自己的包裝。

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具有決定是否返回項目的功能。它的工作原理與TryDequeueConcurrentQueue相似,只是如果隊列中有一個項目,它會返回一個值,該函數將爲該項目返回true。

+0

這可以工作!謝謝 –