CLR 定义的方法(例如 [delegate].BeginInvoke)记录在哪里? [关闭]

2024-01-12

[编辑,完全改写:] 看来我的问题措辞确实不好,而且也没有得到很好的回应。所以我希望这个完整的改写能有所帮助......


Control.Begin/End/Invoke() 和 Dispatcher.Begin/End/Invoke() 方法与委托的 Begin/End/Invoke() 方法具有相同的名称和有些相似的行为,但最好放弃它们的想法是相同的。最重要的区别是委托的方法是类型安全,这是 Control 和 Dispatcher 版本中完全缺失的。运行时行为也非常不同。

CLI 规范中详细说明了管理委托的规则,ECMA 335 http://www.ecma-international.org/publications/standards/Ecma-335.htm,第二章 14.6。最好看一下这一章,我只给出一个概要。

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

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

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

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

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

您在委托对象上看到的任何其他方法都是从基类 MulticastDelegate 和 Delegate 继承的方法。与 DynamicInvoke() 和 GetObjectData() 类似。

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

MSDN是相关的,委托类型的方法是not记录在案。它假设您从规范和委托声明中知道它们的作用以及它们的外观。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CLR 定义的方法(例如 [delegate].BeginInvoke)记录在哪里? [关闭] 的相关文章

随机推荐