以委托方式创建线程
创建线程的一种简单的方式是定义一个委托,并异步调用它。
异步调用委托的方式:投票,等待句柄,异步回调。
1.投票:检查委托是否完成了它的任务。
static int TakesAWhile(int data, int ms) { Console.WriteLine("TakesAWhile started"); Thread.Sleep(ms); Console.WriteLine("TakesAWhile completed"); return ++data; } public delegate int TakesAWhileDelegate(int data, int ms); static void Main(string[] args) { TakesAWhileDelegate dl = TakesAWhile; IAsyncResult ar = dl.BeginInvoke(1, 3000, null, null); //获得该委托的相关信息 while (!ar.IsCompleted) //如果委托没有完成任务 { Console.Write("."); Thread.Sleep(50); } int result = dl.EndInvoke(ar); //EndInvoke()方法会一直等待,直到委托完成其任务。 Console.WriteLine("result:{0}", result); }
2.等待句柄:使用IAsyncResult相关的等待句柄。
使用AsyncWaitHandle属性可以访问等待句柄。这个属性返回一个WaitHandle类型的对象,它可以等待委托线程完成其他任务。
而WaitOne()方法将一个超时时间作为可选的第一个参数,在其中可以定义要等待的最长时间。如果发生超时,WaitOne()方法就返回false,while循环就会继续执行。如果等待操作成功,就用一个中断退出while循环,用委托的EndInvoke()方法接受结果。
static void Main(string[] args) { TakesAWhileDelegate dl = TakesAWhile; IAsyncResult ar = dl.BeginInvoke(1, 3000, null, null); //获得该委托的相关信息 while (ar.AsyncWaitHandle.WaitOne(5,false)) { Console.Write("Can get the result now"); break; } int result = dl.EndInvoke(ar); //EndInvoke()方法会一直等待,直到委托完成其任务。 Console.WriteLine("result:{0}", result); }
3.异步回调
在BeginInvoke()方法的第三个参数中,可以传递一个满足AsyncCallBack委托的需求的方法。AsyncCallBack定义了一个IAsyncResult类型的参数,其返回类型是void。最后一个参数,可以传递任意对象,以便从回调方法中访问它。
现在,只要TakesAWhileDelegate委托完成其任务。就调用TakesAWhileCompleted()方法。不需要在主线程中等待结果。但是在委托线程未完成之前不能停止主线程,除非主线程结束时停止的委托线程没有问题。
使用回调方法,这个方法从委托线程中调用,而不是从主线程中调用。
static int TakesAWhile(int data, int ms) { Console.WriteLine("TakesAWhile started"); Thread.Sleep(ms); Console.WriteLine("TakesAWhile completed"); return ++data; } public delegate int TakesAWhileDelegate(int data, int ms); static void TakesAWhileCompleted(IAsyncResult ar) { if (ar == null) throw new ArgumentNullException("ar"); TakesAWhileDelegate dl = ar.AsyncState as TakesAWhileDelegate; Trace.Assert(dl != null,"Invalid object type"); int result = dl.EndInvoke(ar); Console.WriteLine("result:{0}", result); } static void Main(string[] args) { TakesAWhileDelegate dl = TakesAWhile; dl.BeginInvoke(1, 3000, TakesAWhileCompleted, dl); for(int i = 0;i<100;i++) { Console.Write("."); Thread.Sleep(50); } }