ugeb
asked on
eliminate cross thread errors in vb.net
Hi,
I have a windows form app in VB.net, whereby the main form instantiates a class, Rtu, that has events. I added events to Rtu in order to get a MainForm textbox to display messages from the Rtu class. Not sure if there's a better way send messages.
In any event, in the Rtu init I raise an event which is handled by the mainform class method messageHandler. I added it like this:
System.InvalidOperationExc eption was unhandled
Message=Cross-thread operation not valid: Control 'displayTextbox' accessed from a thread other than the thread it was created on.
http://msdn.microsoft.com/en-us/library/ms171728(v=vs.85).aspx
which talks about thread-safe ways to access components and gives code, but
there was better source code here which I used:
http://www.vbforums.com/showthread.php?575929-Type-SetTextCallback-is-not-defined
The problem is that when the line
How can I fix this?
I have a windows form app in VB.net, whereby the main form instantiates a class, Rtu, that has events. I added events to Rtu in order to get a MainForm textbox to display messages from the Rtu class. Not sure if there's a better way send messages.
In any event, in the Rtu init I raise an event which is handled by the mainform class method messageHandler. I added it like this:
AddHandler rtu.broadcast, _
AddressOf Me.messageHandler
This worked fine on init, but later down the road I encountered a problem and got this error in the messageHandler callback:System.InvalidOperationExc
Message=Cross-thread operation not valid: Control 'displayTextbox' accessed from a thread other than the thread it was created on.
Private Sub messageHandler(ByVal e As String)
Try
displayTextbox.Text = e
Catch ex As Exception
displayTextbox.Text = "Command execution failed "
End Try
End Sub
I looked up the error and found what I thought was a solution here:http://msdn.microsoft.com/en-us/library/ms171728(v=vs.85).aspx
which talks about thread-safe ways to access components and gives code, but
there was better source code here which I used:
http://www.vbforums.com/showthread.php?575929-Type-SetTextCallback-is-not-defined
The problem is that when the line
Me.Invoke(d, New Object() {msg})
is executed, the program just hangs. How can I fix this?
you need to check for InvokeRequired. see https://www.experts-exchange.com/questions/24451200/VB-NET-INVOKE-DELEGATE.html
"the program just hangs"
A hang on Invoke() indicates deadlock, which means the main UI thread is unable to service the Invoke() request. This can happen if you've improperly used SyncLock(), or possibly if you've got a polling loop running in the main UI thread. There are other possibilities...we'd need to see more code to diagnose.
A hang on Invoke() indicates deadlock, which means the main UI thread is unable to service the Invoke() request. This can happen if you've improperly used SyncLock(), or possibly if you've got a polling loop running in the main UI thread. There are other possibilities...we'd need to see more code to diagnose.
ASKER
I do check invokeRequired, which is why I have an invoke statement later on. This is the code block from mainform:
I left the catch block as invalid code on purpose while I'm debugging. It never gets called.
Private Delegate Sub SetTextCallback(ByVal [text] As String)
Private Sub messageHandler(ByVal msg As String)
Try
If Me.displayTextbox.InvokeRequired Then
Dim d As New SetTextCallback(AddressOf messageHandler)
Me.Invoke(d, New Object() {msg})
Else
Me.displayTextbox.Text = msg
End If
Catch ex As Exception
displayTextbox.Text = "Command execution failed "
End Try
End Sub
I have a DDE (Ndde library) system running in the rtu instance which raises the event every time there's a call back. It runs asynchronously and calls a method in rtu (whenever it has data) which in turn raises the event.I left the catch block as invalid code on purpose while I'm debugging. It never gets called.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Yes, BeginInvoke seemed to eliminate the deadlock. Is there any housekeeping I need to do by using BeginInvoke instead of Invoke? Will there be memory or other issues?
None that I can think of. Invoke() is synchronous, while BeginInvoke() is asynchronous. Other than that, they're the same...
ASKER
Thank you, that did the trick!