So I have data that is processed in one thread and put into a queue, then another thread is dequeing the information and performing some actions on it.
Here is the queue
public static class MyConcurrentQueue
{
public static ConcurrentQueue<cRule> _Queue;
public static void EnqueueRuleTrigger(cRule _Rule)
{
MyConcurrentQueue._Queue.Enqueue(_Rule);
}
}
on application_start i have
MyConcurrentQueue._Queue = new ConcurrentQueue<cRule>();
if i want to enqueue a rule i use
MyConcurrentQueue.EnqueueRuleTrigger(_Rule); //We're done enqueue the rule
to dequeue I use
MyConcurrentQueue._Queue.TryDequeue(out _Rule)
I noticed that if enqueued 2 items, 1 after the other in a tight loop that by the time of the first dequeue [separate asynch thread], the data in the log file didn’t match the enqueue anymore
If I put a sleep between the enqueues the log reads the correct values, probably because one item is put in, dequeued, another item put in, dequeued.
I suppose this is because the queue is static and it is storing a reference to _Rule instead of a copy of it. Any ideas on how I can fix this? I need the queue to be accessible to multiple threads that’s why I made it static in the first place.
Thanks in advance.
EDIT
Here is my enqueue and log and dequeue and log logic
while (x<=y)
{
MyConcurrentQueue.EnqueueRuleTrigger(_Rule); //We're done enqueue the string AllText = File.ReadAllText(@"C:\Default\New.txt");
File.WriteAllText(@"C:\Default\New.txt", AllText + "\r\nEnqueue Alert:" +
_Rule.AlertID +":" + _Rule.TriggerStartTime + "-" + _Rule.TriggerEndTime);
}
This is on a separate thread
if ( MyConcurrentQueue._Queue.TryDequeue(out _Rule))
{
... some logic
File.WriteAllText(@"C:\Default\New.txt", AllText + "\r\nDequeue Alert:" +
_Rule.AlertID + ":" + _Rule.TriggerStartTime + "-" + _Rule.TriggerEndTime);
}
this is my log file
Enqueue Alert:64c88289-58a1-499b-ade9-3fa69a32cf47: 4/27/2012 12:00:00 PM-4/27/2012 5:00:00 PM
Enqueue Alert:64c88289-58a1-499b-ade9-3fa69a32cf47: 4/28/2012 2:00:00 PM-4/28/2012 9:00:00 PM
Dequeue Alert:64c88289-58a1-499b-ade9-3fa69a32cf47: 4/28/2012 2:00:00 PM-4/28/2012 9:00:00 PM
Dequeue Alert:64c88289-58a1-499b-ade9-3fa69a32cf47: 4/28/2012 2:00:00 PM-4/28/2012 9:00:00 PM
EDIT: Seems to be an issue with enqueing an object, than changing the same object and enqueing it second time. As result during dequeue it looks like second object overrode the first and was inserted twice, in reality reference to the same object was inserted twice.
Most likely solution is to deep clone before insert. Consider making your objects immutable to simplify synchronization and readability of the code.
Original:
Most likly reason is your logging code is not properly synchronized. Since it looks like you want 2 action to happen atomically (Enqueue + Log or Dequeue+Log) you have to add proper locking around both operations, otherwise order of calls to Queue and Log may be semi-random. Also make sure you correctly handle result of TryDequeue (since it can return false).