Acidic
Acidic

Reputation: 6282

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)

Upvotes: 3

Views: 1325

Answers (4)

Martin James
Martin James

Reputation: 24847

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.

Upvotes: 1

lboshuizen
lboshuizen

Reputation: 2786

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

Upvotes: 0

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726479

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.

Upvotes: 4

Darin Dimitrov
Darin Dimitrov

Reputation: 1038710

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

No, it is safe.

Upvotes: 2

Related Questions