C# CLR定义的方法如[delegate].BeginInvoke在哪里?

C# CLR定义的方法如[delegate].BeginInvoke在哪里?,c#,documentation,msdn,begininvoke,C#,Documentation,Msdn,Begininvoke,[编辑,完全重新措辞:]似乎我的问题确实措词不当,也不受欢迎。因此,我希望这一完整的重新措辞有助于…… MSDN明确规定: 在创建控件句柄的线程上执行委托,通常是GUI线程。并将在创建Dispatcher对象的线程上运行。这将是我创建的任何线程 但对于委托,“BeginInvoke和EndInvoke”,这些调用将在线程池线程上运行。除了这种稍微令人惊讶的不同行为之外,我想知道如何找到自动实现的所有函数的规范 例如:Intelli sense显示我的委托有一个DynamicInvoke()。类确

[编辑,完全重新措辞:]似乎我的问题确实措词不当,也不受欢迎。因此,我希望这一完整的重新措辞有助于……

MSDN明确规定: 在创建控件句柄的线程上执行委托,通常是GUI线程。并将在创建Dispatcher对象的线程上运行。这将是我创建的任何线程

但对于委托,“BeginInvoke和EndInvoke”,这些调用将在线程池线程上运行。除了这种稍微令人惊讶的不同行为之外,我想知道如何找到自动实现的所有函数的规范

例如:Intelli sense显示我的委托有一个DynamicInvoke()。类确实有一个DynamicInvoke(),这可能意味着我的委托继承了它。但是委托{}没有BeginInvoke()。委托{}有几个我的委托没有的函数。我的委托还获得一个GetObjectData()方法。这似乎来自ISerializable

总之,委托似乎是从(1)CLR“自动”获取其方法,(2)委托{}的某个子集可能是多播委托{},可能是(3)ISerializble在哪里可以找到委托获得的所有方法的全面规范?特别有趣的是BeginInvoke(),它是精确的签名,,因为前面提到的两个同名方法具有不同的签名集

[有人在编辑中建议“代表”就是“代表”。我敢说,事实并非如此。]


感谢控件.Begin/End/Invoke()和Dispatcher.Begin/End/Invoke()方法与委托的Begin/End/Invoke()方法具有相同的名称和类似的行为,但最好不要认为它们是相同的。最重要的区别是委托的方法是类型安全的,这在控件和调度程序版本中是完全缺失的。运行时行为也非常不同

CLI规范第II.14.6章详细阐述了管理委托的规则。最好读一下这一章,我只提供一个概要

委托声明转换为从MulticastDelegate继承的类(而不是CLI规范中指定的委托)。该类始终只有4个成员,其运行时实现由CLR提供:

  • 接受对象和IntPtr的构造函数。对象是Delegate.Target,IntPtr是目标方法Delegate.method的地址。这些成员稍后在调用委托时使用,如果委托绑定到的方法是实例方法,则目标属性提供this引用,对于静态方法为null。Method属性确定调用哪个方法。您不直接指定这些参数,当您使用新运算符或使用+=运算符订阅事件处理程序时,编译器会提供这些参数。在事件的情况下使用大量语法,不必显式使用新操作符

  • 调用()方法。方法的参数是动态生成的,并与委托声明相匹配。调用Invoke()方法在同一线程上运行委托目标方法,即同步调用。您很少在C#中使用它,您只使用语法sugar,该语法允许仅使用对象名(后跟括号)调用委托对象

  • BeginInvoke()方法提供了进行异步调用的方法。该方法在目标方法忙于执行时快速完成,类似于ThreadPool.QueueUserWorkItem,但具有类型安全参数。返回类型始终为System.IAsyncResult,用于确定异步调用何时完成并提供给EndInvoke()方法。第一个参数是可选的System.AsyncCallback委托对象,异步调用完成后将自动调用其目标。第二个参数是一个可选对象,它将按原样传递给回调,有助于跟踪状态。其他参数将动态生成并与委托声明匹配

  • 一个EndInvoke()方法。它只接受一个IAsyncResult类型的参数,您必须传递从BeginInvoke()获得的参数。它完成异步调用并释放资源

在委托对象上看到的任何其他方法都是从基类、MulticastDelegate和delegate继承的方法。比如DynamicInvoke()和GetObjectData()

异步调用是很棘手的,您很少需要使用它们。事实上,它们在.NETCore目标中不可用,例如Silverlight。委托目标方法在任意线程池线程上运行,就像Threadpool.QueueUserWorkItem()一样。它可能抛出的任何未经处理的异常都会被捕获并终止线程,但不会终止程序。必须调用EndInvoke(),否则将导致资源泄漏10分钟。如果目标方法引发异常,则在调用EndInvoke()时将重新引发该异常。您无法控制线程池线程,无法取消或中止它。任务或线程类是更好的选择


MSDN是相关的,委托类型的方法没有文档记录。它假定您从规范和委托声明中了解它们的功能和外观

根据你问题的主题,答案将是这些粗体线条。MSDN可能不会更好,但它很好:)

杰弗里·里克特(Jeffrey Richter)写了你在上述问题中提出的问题。他在MSDN杂志上发表了这篇文章。 本文将向您展示如何在.NET CLR中实际实现(可能不是实际实现,但非常接近)此BeginInvoke和EndInvoke。花点时间
public delegate int PerformCalculation(int x, int y);
using System;
// Declare delegate -- defines required signature:
delegate void SampleDelegate(string message);

class TestDelegate
{
    private void CallMeUsingDelegate(string m_param)
    {
        Console.WriteLine("Called me using parameter - " + m_param);
    }

    public static void Main(string[] args)
    {
        // Here is the Code that uses the delegate defined above.
        SampleDelegate sd = new SampleDelegate(CallMeUsingDelegate);
        sd.Invoke("FromMain");
    }
}
class TestDelegate
{
    public static void Main(string[] args)
    {
        // Here is the Code that uses the delegate defined above.
        SampleDelegate sd = delegate(param) {
                        Console.WriteLine("Called me using parameter - " + param);
                    };

        sd.Invoke("FromMain");
    }
}
IAsyncResult ar = sd.BeginInvoke(CallMeUsingDelegate, callMeOnCompletion, sd);