簡體   English   中英

正確使用.NET Concurrent Collections

[英]Proper use of .NET Concurrent Collections

在我嘗試創建並發Socket操作時,我創建了以下代碼:

ConcurrentQueue<byte[]> messageQueue;
ManualResetEvent resetEvent;
Thread outThread;   // -> new Thread(BeginSending);

public void BeginSending() // invoked by outThread
{
    while (true)
    {
        resetEvent.WaitOne();
        while (messageQueue.Count > 0)
        {
            byte[] msg;
            messageQueue.TryDequeue(out msg);
            // send msg via socket
        }
        resetEvent.Reset();
    }
}

public void QueueMessage(byte[] msg) // invoked by the main thread
{
    messageQueue.Enqueue(msg);
    resetEvent.Set();
}

將項目添加到ConcurrentQueue而另一個線程迭代/出列是危險的事情?

根據我的理解,許多同步集合只是單獨同步的方法,但對於concurrentQueue和類似的集合是一樣的嗎?
ConcurrentBagConcurrentDictionaryConcurrentStack

ConcurrentQueue本身沒問題,只要你沒有改變存儲為其元素的數組。

但是,使用ManualResetEvent的使用模式表明有更好的解決方案:如果使用BlockingCollection<T> ,則可以避免進行手動同步。

將項目添加到ConcurrentQueue,而另一個線程迭代/出列是危險的事情?

不,這很安全。

ConcurrentQueue很好,ManualResetEvent不是:

public void BeginSending() // invoked by outThread
{
    while (true)
    {
        resetEvent.WaitOne();
        while (messageQueue.Count > 0)
        {
            byte[] msg;
            messageQueue.TryDequeue(out msg);
            // send msg via socket
        }

    // context change
    messageQueue.Enqueue(msg);
    resetEvent.Set();
    // context change

        resetEvent.Reset();
    }
}

這樣的事件序列將導致忽略排隊的消息。 要么使用其他海報建議的BlockingCollection,要么使用信號量進行信號/等待。

並發集合設計為線程安全的。 使用它們可以自己實現它們,從而為您節省很多麻煩。

請注意,集合本身是同步的,而不是其中的數據。 更新集合中的對象而不關注其他線程可能會帶來競爭條件。

與任何類的使用一樣,如果您了解集合的用法和用例,它會有所幫助

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM