Multi-threading with SyncLock and Invoke

UncleRonin

Well-known member
Joined
Feb 28, 2006
Messages
230
Location
South Africa
Programming Experience
5-10
Once again Invoke has come back to haunt me!

I have an application that has some background threads, serial communications and obviously a GUI. Now, the serial ports received incoming messages as events and these get processed and incoming data is logged both to a file and also appended to a RTB in the GUI (done using Invoke if InvokeRequired is true).

Now, under normal circumstances everything is super happy and runs quite nicely but when stressed I reach some sort of deadlock.

What happens is I have two methods AddOutput and RemoveOutput. These both sync over an object SyncOutput As Object. When messages are received on the serial port they are processed and depending on whether or not a response is required AddOutput is called. This adds out going messages to a dictionary which is then accessed by a thread and the messages are sent out. If an acknowledgement message is received then the corresponding message in the dictionary is removed.

VB.NET:
        SyncLock FMain.SyncOutput
            If Not Me.MyOutputs.ContainsKey(OutputKey) Then
                Me.MyOutputs.Add(OutputKey, Output)
            End If
        End SyncLock
VB.NET:
        SyncLock FMain.SyncOutput
            If Me.MyOutputs.ContainsKey(OutputKey) Then
                Me.LogToFile("INFO: Key being removed." & TempKey, Me.MyLogFileMain)
                Me.MyOutputs.Remove(OutputKey)
            Else
                Me.LogToFile("ERROR: Output not found." & TempKey, Me.MyLogFileMain)
            End If
        End SyncLock

So under stressed conditions AddOutput and RemoveOutput lock BUT only because Invoke is called in LogToFile (where it appends the call to the RTB).

When the deadlock occurs and I Break All in VS it goes to the Invoke call in LogToFile. Why does it block here? I understand that AddOutput is the result of an event as is RemoveOutput but surely since AddOutput is blocking on the SyncLock waiting for RemoveOutput, execution can happen like normal? Does AddOuput wait for RemoveOutput but then when Invoke is called it waits for AddOutput which is currently blocking so nothing can happen after that? Why does the event handling behave like this? Is it the same thing as a sleeping thread (like I had an issue with previously here?)

It works just fine nearly all of the time but as soon as there are a LOT of incoming and outgoing messages the two lock up. Any ideas?
 
SyncLock FMain.SyncOutput
What is FMain? Is it a default form instance? If so it won't work, each thread has it's own set of default form instances, thus each thread will not use same sync object and not lock.
 
In that code FMain.SyncOutput is a shared global. Whether it is FMain.SyncOutput or Me.SyncOutput and it is private to the form the behaviour is the same.
 
Back
Top