Reputation: 6282
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
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
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
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
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