1、创建线程的一种简单方法是首先定义一个委托,如WaitAWhileDelegate。该委托的参数个数和参数类型要与其所将要委托的方法一致,如WaitAWhile方法。实际上委托是类的一种,因此在Program类的外部定义或者在其内部定义作为其内部类都是可以的。接下来使用委托的BeginInvoke方法异步调用它。
1 using System; 2 using System.Threading; 3 4 delegate int WaitAWhileDelegate(int data, int ms); 5 6 class Program 7 { 8 static void Main(string[] args) 9 {10 WaitAWhileDelegate d = WaitAWhile;11 int data = 1;12 int ms = 3000;13 IAsyncResult a = d.BeginInvoke(data, ms, null, null);14 while (!a.IsCompleted)15 {16 Console.Write("*");17 Thread.Sleep(100);18 }19 int result = d.EndInvoke(a);20 Console.WriteLine("\nresult: {0}", result);21 }22 23 static int WaitAWhile(int data, int ms)24 {25 Console.WriteLine("WaitAWhile started.");26 Thread.Sleep(ms);27 Console.WriteLine("WaitAWhile completed.");28 return ++data;29 }30 }
增加代码中第17行的Sleep方法的参数值,输出的星号的个数会减少,反之会增加。
运行结果:
注意:不同于委托的Invoke方法,BeginInvoke方法是异步调用,所以“*”可能会在“WaitAWhile started.”之前输出,如上图所示。
2、IAsyncResult有一个名字叫AsyncWaitHandle的属性,该属性的类型是WaitHandle类。该类的WaitOne方法会“将一个超时时间作为可选的第一个参数,在其中可以定义要等待的最长时间”。
1 using System; 2 using System.Threading; 3 4 class Program 5 { 6 delegate int WaitAWhileDelegate(int data, int ms); 7 8 static void Main(string[] args) 9 {10 WaitAWhileDelegate d = new WaitAWhileDelegate(WaitAWhile);11 int data = 1;12 int ms = 3000;13 IAsyncResult a = d.BeginInvoke(data, ms, null, null);14 while (true)15 {16 Console.Write("*");17 if (a.AsyncWaitHandle.WaitOne(50, false))18 {19 Console.WriteLine("Can get the result now.");20 break;21 }22 }23 int result = d.EndInvoke(a);24 Console.WriteLine("\nresult: {0}", result);25 }26 27 static int WaitAWhile(int data, int ms)28 {29 Console.WriteLine("WaitAWhile started.");30 Thread.Sleep(ms);31 Console.WriteLine("WaitAWhile completed.");32 return ++data;33 }34 }
运行结果:
3、等待结果的第三种方式是异步回调。IAsyncResult还有一个名字叫AsyncState的属性。该属性可以强制类型转换为它的委托。
1 using System; 2 using System.Threading; 3 4 class Program 5 { 6 delegate int WaitAWhileDelegate(int data, int ms); 7 8 static void Main(string[] args) 9 {10 WaitAWhileDelegate d = new WaitAWhileDelegate(WaitAWhile);11 d.BeginInvoke(1, 1000, WaitAWhileComplete, d);12 for (int i = 0; i < 100; i++)13 {14 Console.Write("*");15 Thread.Sleep(50);16 }17 }18 19 static int WaitAWhile(int data, int ms)20 {21 Console.WriteLine("WaitAWhile started.");22 Thread.Sleep(ms);23 Console.WriteLine("WaitAWhile completed.");24 return ++data;25 }26 27 static void WaitAWhileComplete(IAsyncResult a)28 {29 if (a == null)30 {31 throw new ArgumentNullException("a");32 }33 WaitAWhileDelegate d = a.AsyncState as WaitAWhileDelegate;34 if (d == null)35 {36 throw new Exception("a.AsyncState can not convert to WaitAWhileDelegate");37 }38 int result = d.EndInvoke(a);39 Console.WriteLine("\nresult: {0}", result);40 }41 }
注意,第11行代码BeginInvoke方法中的第4个参数d不可以再为null,否则无法实现回调,即无法执行WaitAWhileComplete函数中第39行的打印输出功能。
运行结果:
4、可以使用Lamda表达式代替委托。
1 using System; 2 using System.Threading; 3 4 class Program 5 { 6 delegate int WaitAWhileDelegate(int data, int ms); 7 8 static void Main(string[] args) 9 {10 WaitAWhileDelegate d = new WaitAWhileDelegate(WaitAWhile);11 d.BeginInvoke(1, 1000, a => { int result = d.EndInvoke(a); Console.WriteLine("\nresult: {0}", result); }, d);12 for (int i = 0; i < 100; i++)13 {14 Console.Write("*");15 Thread.Sleep(50);16 }17 }18 19 static int WaitAWhile(int data, int ms)20 {21 Console.WriteLine("WaitAWhile started.");22 Thread.Sleep(ms);23 Console.WriteLine("WaitAWhile completed.");24 return ++data;25 }26 }
运行结果: