异步Async
并行,一般指并行计算,是说同一时刻有多条指令同时被执行,这些指令可能执行于同一CPU的多核上,或者多个CPU上,或者多个物理主机甚至多个网络中。
多线程,一般指同一进程中多个线程(包含其数据结构、上下文与代码片段)协作运行。在多核计算机中多个线程将有机会同时运行于多个核上,如果线程中进行的是计算,则行成并行计算。
异步,与同步相对应,是指呼叫另一操作后,不等待其结果,继续执行之后的操作,若之后没有其他操作,当前线程将进入睡眠状态,而CPU时间将有机会切至其他线程。在异步操作完成后通过回调函数的方式获取通知与结果。异步的实现方式有多种,如多线程与完成端口。多线程将异步操作放入另一线程中运行,通过轮询或回调方法得到完成通知;完成端口,由操作系统接管异步操作的调度,通过硬件中断,在完成时触发回调方法,此方式不需要占用额外线程。 阻塞
异步特点:
1异步不会造成阻塞
2异步可以启用额外的线程去执行任务。
3异步并不会缩短任务的时间
Stopwatch时间统计类
Stopwatch watch = new Stopwatch();
watch.Start();
watch.Stop();
watch.ElapsedMilliseconds//执行事件
异步方法调用
Console.WriteLine("****************异步调用开始**********************");
for (int i = 0; i < 5; i++)
{
string name = string.Format("异步调用{0}", i);
DoHandler method = DoSomething;
method.BeginInvoke("异步调用", null, null);
}
Console.WriteLine("****************异步调用结束**********************");
异步方法(含返回值)调用
//子线程中使用返回值
Console.WriteLine("****************异步待返回值进阶调用开始**********************");
Func<string, long> method = DoSomethingReturn;
//主线程中使用返回值
IAsyncResult result = method.BeginInvoke("异步带返回值调用", t =>
{
long iresult = method.EndInvoke(t);
Console.WriteLine("这里是异步返回值,当前线程={0},计算结果是{1}", Thread.CurrentThread.ManagedThreadId, iresult);
}, null);
异步回调函数
Console.WriteLine("****************异步进阶调用开始**********************");
for (int i = 0; i < 5; i++)
{
string name = string.Format("异步调用{0}", i);
DoHandler method = DoSomething;
AsyncCallback callback = t => Console.WriteLine("当前完成的线程是ID={0},状态参数:{1}", Thread.CurrentThread.ManagedThreadId, t.AsyncState);
//关注参数
//参数2:回调函数
//参数3:回调获得
IAsyncResult result = method.BeginInvoke(name, callback, "Admin");
}
Console.WriteLine("****************异步进阶调用结束**********************");
主线程等待异步结果
方式一:
result.AsyncWaitHandle.WaitOne(-1);//线程一直等待
方式二:
while (!result.IsCompleted)//判断是否结束
{
Thread.Sleep(100);
Console.WriteLine("请继续等待...");//类似进度条
}
方式三:
method.EndInvoke(result)
主线程等待就相当于程序的阻塞。
异步的优缺点:
因为异步操作无须额外的线程负担,并且使用回调的方式进行处理,在设计良好的情况下,处理函数可以不必使用共享变量(即使无法完全不用,最起码可以减少 共享变量的数量),减少了死锁的可能。当然异步操作也并非完美无暇。编写异步操作的复杂程度较高,程序主要使用回调方式进行处理,与普通人的思维方式有些 初入,而且难以调试。
适用范围:
1.在执行I/O操作时
2.网络读写 调用接口
3.数据库的操作
4.WebService
对于需要长时间CPU运算的场合,图形处理,算法执行不适合使用异步。
但是往往由于使用多线程编程的简单和符合习惯,所以很多人往往会使用线程来执行耗时较长的I/O操作,也导致很多人就误认为异步==多线程
总结:需要耗时操作的尽量都使用异步执行。