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

时间:2017-01-03 07:59:36

标签: .net vb.net multithreading invoke begininvoke

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

1

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

2

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

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

1 个答案:

答案 0 :(得分:6)

不,两者之间没有功能差异。只有非常轻微的实现差异,无需担心。使用您喜欢的语法以提高可读性,大多数人都赞成使用snippet(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()。这些方法没有很好的名称,因为它使它们看起来太像委托类型的方法。这有点像设计错误。在this answer中找到细节。