c#异步学习笔记 Task类,async/await
Task理解:字面意思是 “任务”,用来执行异步操作。
Task的用法1:
- 初始化: Task tack = new Task(委托方法); //委托方法也可以是lambda表达式或者匿名函数
- 异步执行委托的方法: task.start();
Task的用法2:
- 直接调用Task封装的静态方法Run: Task.Run(委托方法);//这样在定义玩之后会开一个新线程直接执行委托的方法
注意:系统要执行Task的委托函数时,会开一个新的线程去执行,主线程继续执行下面的代码
async/await用法:
- 主线程碰到await后会立刻返回,以非阻塞的形式执行后面的代码。
- 在Task对象前面用 await会阻塞线程,直到Task中的异步操作结束,并返回结果。程序才会继续执行。
示例demo:(展示task初始化,基本使用)
using System; using System.Threading; using System.Threading.Tasks; namespace ConsoleApplication1 { internal class Program { static void Main(string[] args) { Console.WriteLine("我是主线程,线程ID:" + Thread.CurrentThread.ManagedThreadId); //task用法一 Task task1 = new Task(() => MyAction()); task1.Start(); //task用法二 var strRes = Task.Run<string>(() => { return GetReturnStr(); }); Console.WriteLine(strRes.Result); //task->async异步方法和await,主线程碰到await时会立即返回,继续以非阻塞形式执行主线程下面的逻辑 Console.WriteLine("---------------------------------"); Console.WriteLine("①我是主线程,线程ID:{0}", Thread.CurrentThread.ManagedThreadId); var testResult = TestAsync(); Console.ReadKey(); } static async Task TestAsync() { Console.WriteLine("②调用GetReturnResult()之前,线程ID:{0}。当前时间:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss")); var name = GetReturnResult(); Console.WriteLine("④调用GetReturnResult()之后,线程ID:{0}。当前时间:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss")); Console.WriteLine("⑥得到GetReturnResult()方法的结果一:{0}。当前时间:{1}",await name, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss")); Console.WriteLine("⑥得到GetReturnResult()方法的结果二:{0}。当前时间:{1}", name.GetAwaiter().GetResult(), DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss")); } static async Task<string> GetReturnResult() { Console.WriteLine("③执行Task.Run之前, 线程ID:{0}", Thread.CurrentThread.ManagedThreadId); return await Task.Run(() => { Thread.Sleep(2000); Console.WriteLine("⑤GetReturnResult()方法里面线程ID: {0}", Thread.CurrentThread.ManagedThreadId); return "我是返回值"; }); } static void MyAction() { Console.WriteLine("我是新进程,线程ID:() MyAction " + Thread.CurrentThread.ManagedThreadId); } static string GetReturnStr() { return "我是返回值 ,GetReturnStr 线程ID:" + Thread.CurrentThread.ManagedThreadId; } } }
运行结果:
案例精讲:
using System; using System.Threading; using System.Threading.Tasks; namespace ConsoleApplication1 { internal class Program { static void Main(string[] args) { for (int i = 0; i < 4; i++) { TestAsync(); } Console.ReadLine(); } static async Task TestAsync() { Console.WriteLine("Test()开始, Thread Id: {0}\r\n", Thread.CurrentThread.ManagedThreadId); var name = GetNameAsync(); //我们这里没有用 await,所以下面的代码可以继续执行 // 但是如果上面是 await GetNameAsync(),下面的代码就不会立即执行,输出结果就不一样了。 var res = await name; // Console.WriteLine("await GetName1: {0},得到结果进行其它操作", res); Console.WriteLine("Test()结束.\r\n"); } static async Task<string> GetNameAsync() { // 这里还是主线程 Console.WriteLine("GetName()开始, thread Id is: {0}", Thread.CurrentThread.ManagedThreadId); return await Task.Run(() => { Thread.Sleep(1000); Console.WriteLine("'GetName' Thread Id: {0}", Thread.CurrentThread.ManagedThreadId); return "Jesse"; }); Console.ReadLine(); } } }
输出结果:
代码运行逻辑解析:
- 主线程执行到 for循循环处,调用四个 异步方法 TestAsync();
- 主线程进入TestAsync内部继续执行,遇到异步方法 GetNameAsync();
- 主线程进入GetNameAsync内部继续执行,遇到 await/return 返回,并将 Task任务存储在变量 name 中
- 主线程回到 TestAsync 继续执行 遇到 await name ,开启一个线程,执行Task变量name内部的委托方法,并且,主线程立刻返回,执行下一次循环的 TestAsync 。
- 四次循环的执行逻辑综上所述,因为委托方法内部 让程序 休眠 一秒,也就是 执行委托方法的 四个子线程 都会休眠一秒,但主线程 是一直在执行的。
即:
Test()开始, Thread Id: 1
GetName()开始, thread Id is: 1
首先会连续输出四次,一秒 之后, 四个子线程再输出 委托方法中打印的内容。