根据您问题的主题,答案将是这些粗线。MSDN 可能不会更好,但它很好:)
杰弗里·里希特(Jeffrey Richter)写过您在上面的问题中提出的问题。他在 MSDN 杂志上有这篇文章。 http://msdn.microsoft.com/en-us/magazine/cc164139.aspx
本文将向您展示实际(可能不是实际上但非常接近)BeginInvoke 和 EndInvoke 实际上是如何在 .NET 中实现的CLR。在本文中花一些时间,之后我认为您现在不需要提前阅读。
Jeffrey Richter 在他的 CLR Via C# 一书中也很好地解释了这一点。
大多数 UI 应用程序都是单线程的。UI 上的控件只能使用创建它们的线程来访问。
为了实现这个 Control.Invoke 存在于 Winforms 中。它将自动在 UI 线程上调用您的代码。在 WPF 世界中,我们没有 Control.Invoke。在 WPF 中,我们使用 Dispatcher 而不是 Control。
现在委托与委托。 Hans Passant 提供了一个非常好的答案。
因此,为了深入了解它,我正在写这个答案。
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# 具有这种匿名方法,可用于调用方法而无需将其实际编写为方法。
所以上面的代码也可以写成
使用系统;// 声明委托——定义所需的签名:delegate void SampleDelegate(string message);
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);
这里 Delegate 是您正在调用的方法。将会发生的情况是,您的程序的 Thread 将调用 BeginInvoke 方法,该方法将在内部调用 CLR ThreadPool 线程上的 Delegate 参数中指定的方法。然后你的程序继续运行并返回一个实现 IAsyncResult 接口的对象。您可以使用此对象查询使用您的委托调用的任务的进度(注意作为 3 参数传递的委托 sd)。
CallMeUsingDelegate 方法在单独的线程(ThreadPool 的)上调用。当任务完成时,ThreadPool 将调用指定为 2 参数的 Callback 方法。
看着这一切你可能会想,为什么我们需要 EndInvoke 呢???
这是因为如果你不调用 EndInvoke,CLR ThreadPool 将持有对这个操作的引用,你会泄漏一些内存。因此,在指定的回调方法中调用 EndInvoke 始终是一个好习惯。
我希望这现在可以清除(不是全部),而是一些想法。