BeginInvoke with/without 使用 MethodInvoker——这有什么区别吗?

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

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

1.

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

2.

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

这两种说法是等价的,还是在某些方面有所不同?另外,对于 BeginInvoke() 来说 EndInvoke() 不是必需的吗?

不,两者在功能上没有区别。只有非常细微的实现差异,无需担心。使用您喜欢的语法以提高可读性,大多数人都会喜欢代码段 (2)。

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

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

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

不,您不需要(也不应该)调用 EndInvoke()。这些方法没有很好的名字,因为它使它们看起来太像委托类型的方法。这是一个设计错误。在 this answer.

中找到本质