Reputation: 40032
The below code handles a socket message coming in with a 2 parameters. It puts information into a queue and is processed on another thread. My question is if 2 messages come in right after the other and are then dequeued and sent to the method ProcessData, is there a race condition on ProcessData?
private void DataIn(long Code, string Message)
{
if (!Started)
{
if (DataInQueue == null)
DataInQueue = new Queue();
DataInThread = new Thread(new ThreadStart(ThreadProcedure));
DataInThreadEnding = false;
DataInThread.IsBackground = true;
DataInThread.Start();
Started = true;
}
DataInQueue.Enqueue(new cDataIn(Code, Message));
}
private void ThreadProcedure()
{
while (!ProgramEnding)
{
Queue mySyncdQ = Queue.Synchronized(DataInQueue);
if (mySyncdQ != null && mySyncdQ.Count > 0)
{
cDataIn data = null;
// Creates a synchronized wrapper around the Queue.
if (mySyncdQ.Count > 0)
data = (cDataIn)mySyncdQ.Dequeue();
ProcessData(data);
}
}
}
Upvotes: 1
Views: 2376
Reputation: 10516
Yes I think this can even leave your Queue in an inconstistant state. You should use the Concurrent Queue BlockingCollection that ships with .Net 4. It's threadsafe out of the box and optimzed.
Regards Gert-Jan
Upvotes: 4
Reputation: 70369
UPDATE
Queue is not used in a thread-safe manner in your code... the code you show is not enough to be sure whether there is a race condition but with the ConcurrentQueue
you get a better performance... and in the ThreadProcedure you can have calling ProcessData with null and as far as I can tell to be on the safe side ProcessData should be reentrant for all this to work...
Use a ConcurrentQueue
- that avoids some possible problems... and check out BlockingCollection
which is designed for thread-safe Producer/Consumer scenarios... both work mostly lock-free and are really fast...
Upvotes: 5
Reputation: 244837
Your code is not thread safe. Notice this in the documentation for Queue.Synchronized()
:
To guarantee the thread safety of the
Queue
, all operations must be done through this wrapper only.
You're using the queue directly, so the code is not thread-safe. To fix this, always use just the returned wrapper, as the documentation says.
Or, if you're under .Net 4, use ConcurrentQueue<T>
.
If you wanted to use generic queue on an previous version of .Net, you would could use Queue<T>
and always access it in a lock
.
Upvotes: 3