I am running a MS unit test in VS2010 to test my multi-threaded application.
The application uses an AutoResetEvent
to synchronise threads, which is declared like so:
private readonly AutoResetEvent captureParsedEvent = new AutoResetEvent(false);
The main test thread launches a thread to parse a capture file, and then calls WaitOne()
on a AutoResetEvent
, blocking until the capture is complete:
int id = Thread.CurrentThread.ManagedThreadId;
CaptureManager.Instance.StartProcessingPackets();
Trace.WriteLine("[" + id + "]: WAITING ON CaptureParsedEvent");
captureParsedEvent.WaitOne();
Trace.WriteLine("[" + id + "]: WAITING ON CaptureParsedEvent DONE!");
// Analyse parsed capture...
(Side note: the code originally had a call to captureParsedEvent.Reset()
after WaitOne()
but I removed this while investigating this problem, as my research has concluded that this may not be necessary for AutoResetEvent
objects.)
Meanwhile, the thread which is doing the parsing signals the AutoResetEvent
like this:
private void InstanceManagerStateChanged(ManagerStateEventArgs ea, object sender)
{
int id = Thread.CurrentThread.ManagedThreadId;
switch(ea.CurrentState)
{
case ManagerState.ReadPacketsDone:
Trace.WriteLine("\t[" + id + "]: CaptureParsedEvent SIGNAL");
captureParsedEvent.Set();
Trace.WriteLine("\t[" + id + "]: CaptureParsedEvent DONE!");
break;
}
}
Normally, everything behaves well and I see the following expected output in the output window:
[13]: WAITING ON CaptureParsedEvent
[18]: CaptureParsedEvent SIGNAL
[18]: CaptureParsedEvent DONE!
[13]: WAITING ON CaptureParsedEvent DONE!
However, I am seeing the following output intermittently:
[13]: WAITING ON CaptureParsedEvent
[13]: WAITING ON CaptureParsedEvent DONE!
This is obviously causing me issues because the capture hasn't really finishing parsing.
The above place is the only occurrence of captureParsedEvent.Set();
so I know that nobody else is signalling the event.
A few questions:
Is Trace.WriteLine()
thread-safe and outputting the traces in the correct order?
I have only seen this issue when running unit tests in VS2010 -- is there something funny going on with tests being run in parallel, and usage of threads in this scenario that may be causing issues? My understanding is that the tests run in serial, but not sure if this is correct.
I have resolved my issue.
It turns out that for each packet that the code was processing, it was adding the InstanceManagerStateChanged()
callback to the list of delegates:
CaptureManager.Instance.ManagerStateChanged += InstanceManagerStateChanged;
but we weren't correctly unsubscribing, which meant that I may have been getting notifications from the previous packet.
Unsubscribing prior to processing the next packet fixed this issue:
CaptureManager.Instance.ManagerStateChanged -= InstanceManagerStateChanged;