简体   繁体   中英

Proper use of .NET Concurrent Collections

In my attempt to create concurrent Socket operations, I've created the following code:

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

Is adding items to the ConcurrentQueue while a different thread is iterating/dequeuing it a dangerous thing?

From my understanding many synchronized collections simply have individually synchronized methods, but is the same true for concurrentQueue and similar collections?
( ConcurrentBag , ConcurrentDictionary , ConcurrentStack )

The ConcurrentQueue itself is OK, as long as you are not mutating the arrays stored as its elements.

However, your usage pattern with ManualResetEvent suggests that there is a better solution: if you use BlockingCollection<T> , you would be able to avoid doing manual synchronization.

Is adding items to the ConcurrentQueue while a different thread is iterating/dequeuing it a dangerous thing?

No, it is safe.

The ConcurrentQueue is fine, the ManualResetEvent is not:

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

Such a sequence of events will result in an enqueued message being ignored. Either use a BlockingCollection, as suggested by the other posters, or use a semaphore for signal/wait.

The concurrent collections are designed to be thread safe. Using them saves you a lot of trouble by implementing them yourself.

Be aware though that the collection itself is synchronized, NOT the data inside it. Updating the objects inside the collections without attention for the other threads can bring race-conditions.

As with any usage of a class it helps if you have a understanding of the use and use-cases of the collections

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM