async和await这一组关键字是.Net4.5新增的一种异步编程方式,今天就根据自己的理解讲讲async和await与Task之间的关系。
什么是异步
拿操作系统来说,CPU就具有异步性。当在进行IO的耗时操作时,CPU不会处于阻塞状态,而是可以继续执行其它的指令。编程中异步通常用于打开大文件、上传大文件、发起网络请求等耗时操作,异步操作在应用程序主线程以外的其它线程中执行,主线程可以在异步操作时执行其它操作。
异步与同步的区别
同步:同步是指顺序执行,在执行某个操作时,应用程序必须等待其执行完毕后才能执行下一个操作,举个栗子,到了中午的饭点,而我和同事却有一个棘手的bug要处理(改bug很耗时的,顺便吐槽下,玩游戏时经常听到有人把bug当成3个英文字母念成bi you ji),老大要求不改好不能吃饭,这就是一个同步操作,我们想要吃饭,必须先改完bug。
异步:异步是指在执行某个操作时,应用程序可以在执行异步操作时继续执行其它操作,还是用上面的栗子,老大估摸着这个bug改完,食堂早没饭了,就命令我去改bug,然后他跑去吃饭了,即老大在指挥我改bug的时候,并没有要等我改完才去吃饭,而是自己先跑了,这就是异步。
async和await 的用法
用async和await实现异步编程时,需知以下几点:
- 异步方法需用async关键字描述,且返回类型只能是void、Task、Task ,如果你要执行的异步方法是有返回值的,那么泛型T就定义为你所需返回的类型
- await关键字只能在async声明的异步方法中使用,且其挂起的方法返回类型必须是Task或Task.
- await 会让当前方法等待其挂起的方法执行完毕后再继续执行当前方法。
还是结合代码来说明吧:
C#代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TaskTest
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("主线程运行开始:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId);
Test1();
Console.WriteLine("主线程运行结束:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId);
Console.ReadLine();
}
public static async void Test1()
{
Console.WriteLine("执行异步方法Test1开始:{0}",System.Threading.Thread.CurrentThread.ManagedThreadId);
await Test2();
Console.WriteLine("执行异步方法Test1结束:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId);
}
public static async Task Test2()
{
Console.WriteLine("执行异步方法Test2开始:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId);
Task.Run(() => {
for (int i = 0; i < 10; i++)
{
Console.WriteLine(i + ":线程ID:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId);
}
});
Console.WriteLine("执行异步方法Test2结束:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId);
}
}
}
首先用async定义了两个异步方法Test1()和Test2(),在Main方法中调用Test1(),在Test1()中用await挂起了Test1()方法,让其等待Test2()执行完毕后再执行后面的代码,再来看看Test2(),在Test2()中用Task新开了一个任务线程去执行耗时操作,因为Task前面没有使用await关键字,因而不会阻塞Test2()剩余代码的执行,然后线程控制权交给Test1(),Test1()执行完后,线程控制权交给Main方法。
执行结果:
现在,我们在Test2()方法中的Task.Run前面加上await关键字,再来看看执行结果:
加上await以后,Test2()被挂起,等待Task执行完毕后,才能执行后面的代码,这时候主线程控制权交回给Test1(),而Test1()也被挂起,等待Test2()执行完毕,所以主线程控制权交回给Main方法,从结果上的线程ID可以看出有两个线程在并发处理,这里不要被结果中的打印顺序迷惑,并不是Test2()中的循环执行完毕后才把控制权交回给主线程,我们把i的值设大一点就知道了
,线程7和线程10属于并发执行。
从上面的代码可以看到,async和await实现异步编程与Task密不可分,下一篇在Mark下Task。
个人理解,若有偏差,请指正