C#多线程系列之异步回调(委托)
本⽂参考⾃,纯属读书笔记
在解析异步回调之前,先看同步回调的执⾏过程,以及代码原理。
1、线程的同步执⾏
同步执⾏:在主线程执⾏的时候,主线程调⽤⼀个其它⽅法,此时主线程阻塞,等待调⽤⽅法执⾏完成后主线程才能继续执⾏。
代码如下:
class Program
{
static void Main(string[] args)
{
for (int i = 1; i < 11; i++) {
if (i == 5) {
Console.WriteLine("调⽤TakeAWhile⽅法并等待其执⾏完成");
Console.WriteLine("开始执⾏TakeAWhile⽅法,时间:{0}", DateTime.Now);
int result = TakeAWhile(0, 6000);
if (result == 1) {
Console.WriteLine("TakeAWhile⽅法执⾏完成");
}
Console.WriteLine("TakeAWhile⽅法执⾏完毕,时间:{0}", DateTime.Now);
}
Thread.Sleep(30);
Console.WriteLine(i.ToString());
}
}
static int TakeAWhile(int data, int time) {
Thread.Sleep(time);
return ++data;
}
}
从上⾯的结果得出当程序开始调⽤TakeAWhile⽅法后,主线程阻塞,当TakeAWhile⽅法调⽤完毕之后,主线程⼜重新开始运⾏,这个过程就是线程的同步执⾏的过程.
2、线程的异步执⾏
what is 异步执⾏?
异步执⾏:在主线程执⾏的时候,打开⼀个⼦线程,主线程不会像同步执⾏的那样等待⼦线程的结果返回后在执⾏,主线程会继续执⾏,当主线程需要⼦线程的运⾏结果时,主线程直接调⽤⼦线程的运⾏结果,如果⼦线程的运⾏结果还没有出来,那么主线程等待,直到⼦线程执⾏结束,主线程拿到⼦线程的运⾏结果,主线程在继续。
Func<int, int, int> fun = TakeAWhile;
IAsyncResult ar = fun.BeginInvoke(0, 1000, null, null);//主线程调⽤⼦线程开始执⾏TakeAWhile⽅法,并给它传递了参数int times=1;
while (!ar.IsCompleted)
{
//当⼦线程没有完成之前,主线程可以在该while语句块内进⾏任何后续操作,⽽且不⽤等待⼦线程的结束
Console.WriteLine(times++);
Thread.Sleep(50);
}
int result = fun.EndInvoke(ar);//1秒之后我需要⼦线程的结果了,ok,从⼦线程中拿到结果
Console.WriteLine("TakeAWhile⽅法结束,时间是:{0}", DateTime.Now);
Console.WriteLine("result:{0}", result);
Console.ReadKey();
}
static int TakeAWhile(int data, int times)
{
Console.WriteLine("TakeAWhile⽅法开始执⾏,时间是:{0}",DateTime.Now);
Thread.Sleep(times);
return ++data;
}
}
从结果和代码进⾏分析,当通过BeginInvoke⽅法开始异步执⾏TakeAWhile⽅法,主线程继续执⾏,然后通过IsCompleted属性判断TakeAWhile是否执⾏完成,最后获取⼦线程的输出值,并输出其结果,整个过程主线程没有因为在执⾏⼦线程的原因,⽽造成阻塞
注:因为多线程,导致了这个情况,开启⼦线程和执⾏⼦线程中的⽅法都需要时间,所以主线程的执⾏速度快于⼦线程,所以先输出了⼀个1;解决⽅法很简单,让主线程休息⼀会,等⼦线程先初始化完,代码如下:
Func<int, int, int> fun = TakeAWhile;
IAsyncResult ar = fun.BeginInvoke(0, 1000, null, null);//主线程调⽤⼦线程开始执⾏TakeAWhile⽅法,并给它传递了参数
Thread.Sleep(30);//休息⼀会
int times=1;
while (!ar.IsCompleted)
{
//当⼦线程没有完成之前,主线程可以在该while语句块内进⾏任何后续操作,⽽且不⽤等待⼦线程的结束
Console.WriteLine(times++);
Thread.Sleep(50);
}
int result = fun.EndInvoke(ar);//6秒之后我需要⼦线程的结果了,ok,从⼦线程中拿到结果
Console.WriteLine("TakeAWhile⽅法结束,时间是:{0}", DateTime.Now);
Console.WriteLine("result:{0}", result);
Console.ReadKey();
}
static int TakeAWhile(int data, int times)
{
Console.WriteLine("TakeAWhile⽅法开始执⾏,时间是:{0}",DateTime.Now);
Thread.Sleep(times);
return ++data;
}
}
3、异步回调
what is 异步异步回调?
异步回调:主线程在执⾏的时候,打开⼀个⼦线程,主线程继续执⾏,当⼦线程执⾏完成的时候,主线程⽴即输出⼦线程的运⾏结果,主线程继续执⾏。
Func<int, int, int> fun = TakeAWhile;
fun.BeginInvoke(0, 1000, TakesAWhileCallBack, fun);//异步调⽤TakeAWhile,并指定回调函数TakesAWhileCallBack for (int i = 0; i < 20; i++)
{
Console.WriteLine(i.ToString());
Thread.Sleep(100);
}
Console.ReadKey();
}
static int TakeAWhile(int data, int times) {
Console.WriteLine("TakeAWhile⽅法开始执⾏,时间是:{0}", DateTime.Now);
Thread.Sleep(times);
return ++data;
writeline函数}
///<summary>
///回调函数
///</summary>
///<param name="fun">调⽤的委托</param>
static void TakesAWhileCallBack(IAsyncResult fun)
{
if (fun == null)
throw new ArgumentNullException("fun");
Func<int, int, int> dl = (Func<int, int, int>)fun.AsyncState;
int result = dl.EndInvoke(fun);
Console.WriteLine("我是回调函数返回的结果:{0}", result);
Console.WriteLine("TakeAWhile执⾏完成,时间是:{0}", DateTime.Now);
}
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论