谁向类型化委托添加BeginInvoke、Invoke和EndInvoke方法定义?

3
例如,如果您编写...
public delegate void MyTypedDel(int x)
Intellisense 显示 BeginInvoke、Invoke 和 EndInvoke 是 MyTypedDel 类型定义的一部分。
它们不是 Delegate 或 MulticastDelegate 类型定义的一部分。(Delegate 有一个 DynamicInvoke 方法,它使用晚期/运行时绑定来绑定到方法。)

所以我的问题是这些方法混合到类型化委托类型定义的哪里,它的实现是什么样子的?我读到了... Invoke 在同一线程上依次调用 BeginInvoke 和 EndInvoke。这是真的吗?

只是好奇内部的魔法...也许我错过了一些非常明显的东西...在这种情况下,请毫不留情 :)

2个回答

5
编译器会为您生成委托类,该类继承自Delegate BCL类,并添加特定于委托签名的方法。您可以通过在反射器中查看您的委托(或BCL委托)并切换到IL视图来查看此内容(因为C#反汇编器足够智能,能将其转换回委托声明)。示例:
.class public auto ansi sealed WaitCallback
    extends System.MulticastDelegate
{
    .custom instance void System.Runtime.InteropServices.ComVisibleAttribute::.ctor(bool) = { bool(true) }
    .method public hidebysig specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed
    {
    }

    .method public hidebysig newslot virtual instance class System.IAsyncResult BeginInvoke(object state, class System.AsyncCallback callback, object 'object') runtime managed
    {
    }

    .method public hidebysig newslot virtual instance void EndInvoke(class System.IAsyncResult result) runtime managed
    {
    }

    .method public hidebysig newslot virtual instance void Invoke(object state) runtime managed
    {
    }

}

为什么.method块是空的,也就是说这些方法的实现/IL在哪里?这些调用被路由到哪里了? - Gishu
我认为这与运行时托管元数据有关。我猜这相当于一个InternalCall,意味着CLR在内部实现这些方法。 - Kent Boogaart
在Jeffrey Richter的CLR via C# 2.0书中找到了我的答案——关于委托的章节。当您使用委托关键字时,编译器会创建一个派生自MulticastDelegate的新类型,并添加一个构造函数Invoke(),其签名与您指定的委托相同,并相应地添加BeginInvoke()和EndInvoke()。 - Gishu

1
编译器会完成大部分工作(请参考肯特的回复)。关于连续调用Begin/End的问题,对于委托来说是不需要的。你可以验证这一点,因为BeginInvoke将工作推送到ThreadPool,而如果使用Invoke,则工作将在当前线程上执行。
然而,这种方法在其他一些Begin/End配对中很常见(特别是IO绑定操作),但不适用于委托。
我一直在寻找更优雅的调用Begin/End的方法(而不必涉及IAsyncResult等)- 请参阅此处了解更多信息

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接