BeginInvoke with/without using MethodInvoker—does it make any difference?

829 views Asked by At

I've seen these 2 versions of code while looking at some other developers' code:

1.

    Me.BeginInvoke(New MethodInvoker(Sub() cbo.ShowPopup()))

2.

    Me.BeginInvoke(Sub()
                      cbo.ShowPopup()
                   End Sub)

Are both statements equivalent, or are they different in some way? Also, isn't EndInvoke() necessary with BeginInvoke()?

1

There are 1 answers

0
Hans Passant On BEST ANSWER

No, there is no functional difference between the two. There is only a very slight implementation difference, nothing to worry about. Use the syntax you favor for readability, most anybody would favor snippet (2).

Some odds that snippet (1) was written by a C# programmer. The first argument of BeginInvoke is System.Delegate, which is the base class of all delegate types. C# demands that you use a specific delegate type, because it is a very strongly type-safe language. But VB.NET has a reputation for (almost) being a dynamic language and does not make the same demand, not even with Option Strict On in effect.

I recommend you use the ildasm.exe utility to look at the generated code for both statements. You'll see that they produce the exact same code. Just one very small difference: the compiler uses a different delegate type. Necessarily so, as it has no special knowledge of MethodInvoker. That delegate type is auto-generated from the lambda expression and has a wonky name like VB$AnonymousDelegate_0. That might give the just-in-time compiler slightly more work to do, assuming that you use MethodInvoker consistently and don't use Ngen. Very hard to qualify, and impossible to measure accurately. It is just a one-time cost, and nothing to worry about.

The other detail is type-safety, the kind that C# demands. You could intentionally break the code by using, say, Sub(arg As Integer) for the lambda expression. That will crash the program at runtime since the arg argument is not available. If you use MethodInvoker then you'll get a compile-time error. That's better than trying to debug the runtime error. But it is just as likely that you'll change the delegate type to Action(Of Integer) and it will still crash.

And no, you don't need to (and shouldn't) call EndInvoke(). These methods do not have very good names since it makes them look too much like the methods of a delegate type. This is a bit of a design mistake. Find the nitty-gritty in this answer.