-->

像[代表]在哪里CLR定义的方法.BeginInvoke记录? [关闭](Where are C

2019-07-20 04:29发布

[编辑,完全改写:]好像我的问题确实不好措辞,并收到不良了。 所以我希望这个完整的改写帮助...

MSDN告诉明确规定: Control.BeginInvoke()执行的线程上的委托,该控件的句柄上创建,通常这会是GUI线程。 和Dispatcher.BeginInvoke()将在其中创建调度对象的线程上运行。 这将是我创建的任何线程。

但对于代表们的“ CLR自动定义的BeginInvoke和EndInvoke”和这些调用上一个线程池线程上运行,而不是。 除了这个令人惊讶的略有不同的行为,我不知道我怎么能找到的,可以自动获得实现的所有功能规格。

例如:智能影音感表明,我委托具有DynamicInvoke()。 类System.Delegate {}确实有一个DynamicInvoke(),这可能意味着我的委托继承它。 但是,代表{}没有的BeginInvoke()。 和委托{}有我的代表还没有几个功能。 同时我代表获得一个GetObjectData使用()方法。 这似乎是来自ISerializable的。

因此,在结束时,委托显示获得它的方法从(1)的CLR “自动地”,(2)代表{}可能MulticastDelegate {},以及可能的(3)ISerializble的一些子集。 我在哪里可以找到的所有方法的委托得到全面规范? 特别有趣的是的BeginInvoke(),它的确切签名,与该名称上述两种方法有不同的组签名。

[有人在一个编辑,一个“代表”是“代表”建议。 我敢说,这不是。]

谢谢

Answer 1:

该Control.Begin /结束/ Invoke的()和Dispatcher.Begin /结束/ Invoke的()方法具有相同的名称和有点类似行为的委托的开始/结束/ Invoke的()方法,但它肯定是最好打消这个想法,他们是相同的。 最重要的区别是,委托的方法是类型安全的 ,东西是完全从控制和调度版本失踪。 运行时的行为是非常不同的。

支配委托的规则进行了详细的CLI规范,规定了ECMA 335章II.14.6。 最好是阅读的章节,我只给一个大纲。

甲委托声明变换成从MulticastDelegate继承(如CLI规范中指定不委派)的类。 这个类总是恰好有4个成员,它们的运行时实现是由CLR提供:

  • 一个构造函数的对象和一个IntPtr。 对象是Delegate.Target,所述IntPtr的是目标方法,Delegate.Method的地址。 这些部件使用后,当你调用委托,目标属性提供了参考,如果到委托绑定的方法是一个实例方法,空的静态方法。 Method属性确定哪些方法被调用。 您不直接指定这些参数,当你使用new运算符或+ =运算符订阅事件处理程序编译器提供它们。 随着大量的事件的情况下,语法糖的,你没有明确地使用新的运营商。

  • 一个Invoke()方法。 该方法的参数是动态生成和匹配委托声明。 调用调用()方法运行在同一个线程, 同步调用对委托目标方法。 你很少能在C#中使用它,你只需要使用语法糖,允许委托对象通过只使用对象名称,后面用括号调用。

  • 一个的BeginInvoke()方法,提供了一种方法,使异步调用。 该方法快速完成,而目标的方法是忙于执行,类似于ThreadPool.QueueUserWorkItem但类型安全的争论。 返回类型总是System.IAsyncResult,用于找出当异步呼叫完成,并提供给EndInvoke会()方法。 第一个参数是一个可选的System.AsyncCallback委托对象,异步调用完成时,它的目标将自动被调用。 第二个参数是一个可选的对象 ,它将被原样传递给回调,有用的跟踪状态。 额外的参数是动态生成和匹配委托声明。

  • 一个EndInvoke会()方法。 这需要IAsyncResult类型的一个参数,你必须通过你的BeginInvoke得到了一个()。 它完成了异步调用,并释放资源。

你委托对象上看到的任何附加的方法是从基类,MulticastDelegate和代表继承而来的。 像DynamicInvoke()和GetObjectData使用()。

异步调用的棘手那些和你很少需要使用它们。 他们实际上在.NETCore目标不可用,像Silverlight。 委托目标方法上的任意线程池中的线程上运行,就像Threadpool.QueueUserWorkItem()一样。 任何未处理的异常可能抛出被捕获并终止线程,但不是你的计划。 你必须调用EndInvoke(),不这样做会造成资源泄漏10分钟。 ()如果目标方法抛出异常,那么它会在您调用EndInvoke重新提出。 你必须在线程池中的线程没有控制,没有办法取消或终止它。 该任务或线程类是更好的选择。

MSDN是相关的,委托类型的方法没有记载。 它假定你知道他们做什么,他们看起来像从规范和委托声明什么。



Answer 2:

根据你的问题的题目的答案会是这些大胆的线条。 MSDN可能不是更好,但它是好的,但:)

杰弗里里希特写关于你问你的问题上面。 他这篇文章的MSDN杂志。 http://msdn.microsoft.com/en-us/magazine/cc164139.aspx这篇文章将告诉你如何实际(可能不实际,但非常接近)这个的BeginInvoke和EndInvoke实际上是在.NET中实现的实现CLR。 花些时间在这篇文章中,之后我现在不认为你需要读。 杰弗里里希特也有在他的书CLR通过C#解释这一切都非常好。

大多数UI应用程序是单线程的。 在UI控件只能使用与创建它们的线程访问。

要达致这Control.Invoke存在的WinForms。 它会自动调用UI线程上的代码。 在WPF的世界里,我们没有Control.Invoke。 在WPF中,我们有调度员,而不是控制。

现在委托VS代表。 汉斯帕桑特已经提供了一个非常好的答案。

所以住一点进去,我写这个答案。

代表MSDN上提到的一类。 让我们这个代码(从MSDN采取http://msdn.microsoft.com/en-us/library/ms173171(v=vs.80).aspx )

public delegate int PerformCalculation(int x, int y);

正如你可以看到我们在这里有代表(注意用小“d”)。 这是定义一个委托或把它在简单的话的关键字,这是定义实际上包含于方法的引用的变量PerformCalculation关键字。

我想你已经意识到这一点,但只是为了完整性。

我们使用这个变量和使用这样的代码调用一个方法:

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");
    }
}

我们调用一个方法,你需要写一个完整的方法如上CallMeUsingDelegate方法。 C#具有可用于调用方法而实际上不必将它写为方法这个匿名的方法

所以,上面的代码也可以写成

使用系统; //声明代表 - 定义所需的签名:委托无效SampleDelegate(字符串消息);

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");
    }
}

这不同样的工作上面的代码。 但是,现在我们需要编写一些代码更少。 编译器将创建用于上述的版本,两个相同的IL代码。 但在2情况下,新方法将被编译器自动生成的名称。

当涉及到的BeginInvoke和EndInvoke,它们用于异步调用的方法。 这是使用线程池这是可用的CLR实现。

基本上发生的事情是,你使用调用方法

IAsyncResult ar = sd.BeginInvoke(CallMeUsingDelegate, callMeOnCompletion, sd);

这里委托方法所调用。 会发生什么事是你的程序将调用BeginInvoke方法,这将在内部调用在一个线程池CLR线程委派参数指定的方法的线程。 然后,你的程序继续运行并返回一个实现IAsyncResult接口的对象。 你可以使用这个对象来查询有关任务的进度使用委托(注意代表SD为3参数传递)调用。

CallMeUsingDelegate方法被调用在单独的线程(线程池的)。 当任务将完成,线程池将调用指定为2参数的回调方法。

看着这一切,你可能会想,为什么我们需要EndInvoke会再???

那么这是因为,如果你不调用EndInvoke会时,CLR线程池将坚持这一操作的参考,你会泄露一些内存。 因此,它始终是一个很好的做法,调用EndInvoke中指定的回调方法。

我希望这现在清除(不是全部),但一些想法。



文章来源: Where are CLR-defined methods like [delegate].BeginInvoke documented? [closed]