UncleRonin
Well-known member
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.
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?
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?