线程、任务和同步学习笔记(一)
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 }
运行结果: