简体   繁体   English

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

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

I've seen these 2 versions of code while looking at some other developers' code: 在查看其他开发人员的代码时,我已经看到了这两个版本的代码:

1. 1。

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

2. 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()? 另外,BeginInvoke()不是必需的EndInvoke()吗?

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). 使用您喜欢的语法以提高可读性,大多数人都赞成使用代码段(2)。

Some odds that snippet (1) was written by a C# programmer. 片段(1)的一些可能性是由C#程序员编写的。 The first argument of BeginInvoke is System.Delegate , which is the base class of all delegate types. BeginInvoke的第一个参数是System.Delegate ,它是所有委托类型的基类。 C# demands that you use a specific delegate type, because it is a very strongly type-safe language. C#要求您使用特定的委托类型,因为它是一种非常强类型安全的语言。 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. 但VB.NET以(几乎)是一种动态语言而闻名,并没有提出相同的需求,即使有效的Option Strict On没有。

I recommend you use the ildasm.exe utility to look at the generated code for both statements. 我建议您使用ildasm.exe实用程序查看两个语句的生成代码。 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. 必然如此,因为它没有MethodInvoker的特殊知识。 That delegate type is auto-generated from the lambda expression and has a wonky name like VB$AnonymousDelegate_0 . 该委托类型是从lambda表达式自动生成的,并且有一个像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. 假设你一直使用MethodInvoker并且不使用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. 另一个细节是类型安全,C#要求的类型。 You could intentionally break the code by using, say, Sub(arg As Integer) for the lambda expression. 您可以通过使用lambda表达式的Sub(arg As Integer)来故意破坏代码。 That will crash the program at runtime since the arg argument is not available. 由于arg参数不可用,这将在运行时使程序崩溃。 If you use MethodInvoker then you'll get a compile-time error. 如果您使用MethodInvoker,那么您将收到编译时错误。 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. 但是,您可能会将委托类型更改为Action(Of Integer) ,但它仍然会崩溃。

And no, you don't need to (and shouldn't) call EndInvoke(). 不,你不需要(也不应该)调用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 . 这个答案中找到细节。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM