理解:
1、async修饰的方法可以理解为异步法(必须与await配合,否则与普通方法无异)2、当async方法执行遇到await时,立即将控制权转移到async方法的调用者3、调用者决定是否需要等待async方法执行,然后继续执行4、await将悬挂当前方法,即阻止当前方法继续执行,将控制权转移给调用者
注:如果调用async方,请注意: 如果不使用await关键字来标记起点,程序将忽略async关键字并以同步的方式执行。编译器会警告类似的问题。
例1:(控制台程序)
1 static void Main(string[] args) 2 { 3 MyMain();//由于main方法不能定义为async,顾此定义了Mymain方法来表示main方法。 4 Console.Read(); 5 } 6 static async void MyMain() 7 { 8 Console.WriteLine(开始实施main方法); 9 AsyncAction();10 Console.WriteLine(继续实施main方法);11 Console.WriteLine(main方法执行结束);12 }13 14 static async Task<string> AsyncAction()15 {16 Console.WriteLine(Asyncaction方法await之前);17 string result = await Task<string>.Run(() =>18 {19 Thread.Sleep(1000);20 Console.WriteLine(Asyncaction方法sleep一秒后);21 return “Asyncaction返回值”;22 });23 Console.WriteLine(Asyncaction方法await后-{0}” result);24 return result;25 }
执行结果:
从返回结果可以看出,这种异步方法Asyncaction执行遇到await,即程序执行到此行时立即挂起,将控制权交给Mymain方法,Mymain决定是否等待Asyncaction执行后再往下执行。Asyncaction方法中的awaition Task.Run(包括)代码将异步执行。
例子二:例子一:MyMain方法执行Asyncaction前加awaition
1 static void Main(string[] args) 2 { 3 MyMain();//由于main方法不能定义为async,顾此定义了Mymain方法来表示main方法。 4 Console.Read(); 5 } 6 static async void MyMain() 7 { 8 Console.WriteLine(开始实施main方法); 9 await AsyncAction();10 Console.WriteLine(继续实施main方法);11 Console.WriteLine(main方法执行结束);12 }13 14 static async Task<string> AsyncAction()15 {16 Console.WriteLine(Asyncaction方法await之前);17 string result = await Task<string>.Run(() =>18 {19 Thread.Sleep(1000);20 Console.WriteLine(Asyncaction方法sleep一秒后);21 return “Asyncaction返回值”;22 });23 Console.WriteLine(Asyncaction方法await后-{0}” result);24 return result;25 }
执行结果:
由于Asyncaction方法在执行前增加了await,Mymain方法必须等到执行结束后才能继续执行。
使用场景及用法分析:
当某个操作执行时间较长或执行结果对整个程序执行影响不大时(一般来说,这个操作是一种独立的方法。)主线程的执行不依赖于此操作的执行结果。它在一些IO操作中很常见,如日志记录。触发日志动作记录时,应单独执行一个线程。此时,无论日志记录是否成功,都不应阻止主线程的执行。在上面的例子一中,AsyncAction方法中可以使用 Task.Run 作为记录日志的动作,当程序执行到 await Task.Run后,Asyncaction方法立即挂起,主线程Mymain继续执行。有人可能会在这里提问?为什么不直接在主线程MyMain中打开线程呢? Task.Run 记录日志?相反,在AsyncAction方法中定义处理日志是必要的。是的,如果这个时候只是为了记录日志,那就不用写一个方法了。但是,首先,这种单一功能的操作应该是独立写在一种方法中。其次是 Asyncaction方法 中的 await Task.Run 返回值可能还有其他操作。
以下例子:在记录日志之前,您需要获取一些登录用户的信息,并将用户信息保存在日志中。如果您将其写入主线程Mymain,则无法避免堵塞主线程(因为您需要等待获取用户信息)。当然,您也可以将这两种方法写在一种方法中,由Task调用。这里只是一个例子来解释Async和Await的使用场景。
1 static void Main(string[] args) 2 { 3 MyMain();//由于main方法不能定义为async,顾此定义了Mymain方法来表示main方法。 4 Console.Read(); 5 } 6 static async void MyMain() 7 { 8 Console.WriteLine(开始实施main方法); 9 WriteUserLog();10 Console.WriteLine(继续实施main方法);11 Console.WriteLine(main方法执行结束);12 }13 14 static async void WriteUserLog()15 {16 Console.WriteLine(“在获取用户信息之前”);17 string userInfo = await GetUserInfoAsync(); ///尽早使用await,为了尽快挂起这种方法(异步执行)18 Console.WriteLine(写入日志前”);19 WriteLog(userInfo);20 }21 22 static Task<string> GetUserInfoAsync()23 {24 return Task.Factory.StartNew(() => {25 Thread.Sleep(1000);26 Console.WriteLine(“完成用户信息获取”);27 return "jxf";28 });29 }30 31 static void WriteLog(string userInfo)32 {33 Thread.Sleep(1000);34 Console.WriteLine(写入日志完成,用户信息:{0} userInfo);35 }
执行结果: