异步委托提供以异步方式调用同步方法的能力。当同步调用一个委托时,“Invoke”方法直接对当前线程调用目标方法。如果编译器支持异步委托,则它将生成“Invoke”方法以及“BeginInvoke”和“EndInvoke”方法。如果调用“BeginInvoke”方法,则公共语言运行库 (CLR) 将对请求进行排队并立即返回到调用方。将对来自线程池的线程调用该目标方法。提交请求的原始线程自由地继续与目标方法并行执行,该目标方法是对线程池线程运行的。如果在对“BeginInvoke”方法的调用中指定了回调方法,则当目标方法返回时将调用该回调方法。在回调方法中,“EndInvoke”方法获取返回值和所有输入/输出参数。如果在调用“BeginInvoke”时未指定任何回调方法,则可以从调用“BeginInvoke”的线程中调用“EndInvoke”。
使用用户指定的委托签名,编译器应发出具有“Invoke”、“BeginInvoke”和“EndInvoke”方法的委托类。“BeginInvoke”和“EndInvoke”方法应被修饰为本机的。因为这些方法被标记为本机的,所以 CLR 在类加载时自动提供该实现。加载程序确保它们未被重写。
NET Framework 允许您异步调用任何方法。为此,应定义与您要调用的方法具有相同签名的委托;公共语言运行库会自动使用适当的签名为该委托定义 BeginInvoke 和 EndInvoke 方法。
BeginInvoke 方法可启动异步调用。它与您需要异步执行的方法具有相同的参数,另外它还有两个可选参数。第一个参数是一个 AsyncCallback 委托,该委托引用在异步调用完成时要调用的方法。第二个参数是一个用户定义的对象,该对象可向回调方法传递信息。BeginInvoke 立即返回,不等待异步调用完成。BeginInvoke 会返回 IAsyncResult,这个结果可用于监视异步调用进度。
EndInvoke 方法检索异步调用的结果。调用 BeginInvoke 后可随时调用 EndInvoke 方法;如果异步调用尚未完成,EndInvoke 将一直阻止调用线程,直到异步调用完成后才允许调用线程执行。EndInvoke 的参数包括您需要异步执行的方法的 out 和 ref 参数(在 Visual Basic 中为 <Out>ByRef 和 ByRef)以及由 BeginInvoke 返回的 IAsyncResult。
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Data;
5 using System.Drawing;
6 using System.Linq;
7 using System.Text;
8 using System.Windows.Forms;
9 using System.Threading;
10 using System.Runtime.Remoting.Messaging;
11
12
13 namespace WindowsFormsApplication3
14 {
15 public delegate void ComplexProcessDelegate();
16 public delegate string GetDateDelegate();
17 public partial class Form1 : Form
18 {
19 public Form1()
20 {
21 InitializeComponent();
22 }
23
24 private void button1_Click(object sender, System.EventArgs e)
25 {
26 MessageBox.Show("GetDate process is begin.");
27 GetDateDelegate gd = new GetDateDelegate(this.GetCurrentDate);
28 gd.BeginInvoke(new AsyncCallback(this.CallbackMethod), null);
29 }
30
31 // Invoke a complex process.
32 private void button2_Click(object sender, System.EventArgs e)
33 {
34 MessageBox.Show("Complex process is begin.");
35 ComplexProcessDelegate cpd =
36 new ComplexProcessDelegate(this.DoComplexWork);
37
38 // cpd(); // synchornized invoke.
39 IAsyncResult iar = cpd.BeginInvoke(null, null); // aynchornized invoke.
40 // iar.AsyncWaitHandle.WaitOne(); // waiting util the process is over.
41 // Synchornized ...
42 MessageBox.Show("Complex process is end.");
43 }
44
45 private void DoComplexWork()
46 {
47 System.Threading.Thread.Sleep(5000);
48 }
49
50 private string GetCurrentDate()
51 {
52 for (int i = 0; i < 500000000; i++)
53 {
54 if (i%1000000 == 0)
55 {
56 i = i + 1;
57 }
58 }
59 return DateTime.Now.ToString();
60 }
61
62 private void CallbackMethod(IAsyncResult iar)
63 {
64 AsyncResult ar = (AsyncResult)iar;
65 GetDateDelegate gd = (GetDateDelegate)ar.AsyncDelegate;
66 string msg = gd.EndInvoke(iar);
67 MessageBox.Show(msg);
68 }
69
70
71 }
72 }
73