VB.NET Invoke Method
Asked Answered
H

3

8

I have this method in my code:

Private Sub Display()
        Received.AppendText(" - " & RXArray)
End Sub

Whats the difference between this 2 calls:

Me.Invoke(New MethodInvoker(AddressOf Display))

AND

Display()

I know that is something about threading, but I'm not sure.

Thanks in advance

Huckleberry answered 18/7, 2013 at 7:52 Comment(2)
See https://mcmap.net/q/1323850/-cross-thread-operation-not-valid-vb-net/11683Apartment
The difference is that Invoke() highly increase the odds your program will hang with a deadlock. Always use BeginInvoke() instead. Particularly troublesome with the SerialPort class, the kind of class where you have to use BeginInvoke in the DataReceived event handler since it runs on a worker thread and thus cannot directly update controls. Using Invoke() causes deadlock when you call the SerialPort.Close() method.Spates
A
12

Use the Invoke way when you're working in different threads. For example if the caller is not in the same thread as the GUI.

If the caller doesn't need to wait for the result of the method, you could even use BeginInvoke:

GuiObject.BeginInvoke(New MethodInvoker(AddressOf Display))

Or shorter:

GuiObject.BeginInvoke(Sub() Display)

For more ease of writing you could move the invoking into the Display function:

Private Sub Display()
    If Me.InvokeRequired Then
        Me.Invoke(Sub() Display)
        Return
    End IF
    Received.AppendText(" - " & RXArray)
End Sub

That way the caller doesn't have to know whether he is in the same thread or not.

Avelinaaveline answered 23/7, 2013 at 11:57 Comment(1)
Personally, I hate this use of recursion -- someone reading the code for the first time has to expend effort to understand WHY recursion is needed, and to make sure that it won't result in an INFINITE LOOP. IMHO much better to write a private sub DisplayMustBeOnUIThread that does the work, and then a wrapper subroutine Display that calls it directly or via invoke if required. Private Sub Display() If Me.InvokeRequired Then Me.Invoke(Sub() DisplayMustBeOnUIThread) Else DisplayMustBeOnUIThread() End SubLakenyalaker
G
5

Adding parameters to the other answer:

Private Sub Display(ByVal strParam As String)
    If Me.InvokeRequired Then
        Me.Invoke(Sub() Display(strParam))
        Return
    End IF
    Received.AppendText(" - " & RXArray)
End Sub
Gave answered 29/4, 2015 at 21:51 Comment(0)
R
1

For future readers, you could also update your UI object by doing the following

Private Sub Display()
    If Me.InvokeRequired Then
        Me.Invoke(Sub()  Received.AppendText(" - " & RXArray))
        Return
    End IF

End Sub
Resort answered 8/4, 2018 at 13:41 Comment(1)
If invoke is not required then your code doesn't update the GUI at all. This is a bugNeolamarckism

© 2022 - 2024 — McMap. All rights reserved.