使用/不使用MethodInvoker的BeginInvoke - 它有什么区别吗?

MJ *_*han 6 .net vb.net multithreading invoke begininvoke

在查看其他开发人员的代码时,我已经看到了这两个版本的代码:

1.

    Me.BeginInvoke(New MethodInvoker(Sub() cbo.ShowPopup()))
Run Code Online (Sandbox Code Playgroud)

2.

    Me.BeginInvoke(Sub()
                      cbo.ShowPopup()
                   End Sub)
Run Code Online (Sandbox Code Playgroud)

两种陈述是否相同,或者它们在某种程度上有所不同?另外,BeginInvoke()不是必需的EndInvoke()吗?

Han*_*ant 6

不,两者之间没有功能差异.只有非常轻微的实现差异,无需担心.使用您喜欢的语法以提高可读性,大多数人都赞成使用代码段(2).

片段(1)的一些可能性是由C#程序员编写的.BeginInvoke的第一个参数是System.Delegate,它是所有委托类型的基类.C#要求您使用特定的委托类型,因为它是一种非常强类型安全的语言.但VB.NET以(几乎)是一种动态语言而闻名,并没有提出相同的需求,甚至没有Option Strict On效果.

我建议您使用ildasm.exe实用程序查看两个语句的生成代码.你会看到他们生成完全相同的代码.只有一个非常小的区别:编译器使用不同的委托类型.必然如此,因为它没有MethodInvoker的特殊知识.该委托类型是从lambda表达式自动生成的,并且名称很像VB$AnonymousDelegate_0.假设你一直使用MethodInvoker并且不使用Ngen,这可能会给即时编译器做更多的工作.很难获得资格,也无法准确衡量.这只是一次性费用,无需担心.

另一个细节是类型安全,C#要求的类型.你可以通过使用Sub(arg As Integer)lambda表达式来故意破坏代码.由于arg参数不可用,这将在运行时使程序崩溃.如果您使用MethodInvoker,那么您将收到编译时错误.这比尝试调试运行时错误更好.但是,您可能会将委托类型更改为Action(Of Integer),但它仍然会崩溃.

不,你不需要(也不应该)调用EndInvoke().这些方法没有很好的名称,因为它使它们看起来太像委托类型的方法.这有点像设计错误.在这个答案中找到细节.