await 和 Async 初探
2014-04-03 21:31
429 查看
在最近的项目中, 各种await关键字到处乱串,所以很有必要来了解下await和async 异步编程。
首先来了解些基本的概念:
1.
构建一个异步函数:
1) 申明时加入async 或Async 修饰符
2)返回值定义为 Task (普通函数中的void) 或 Task<T>(普通函数中的返回值)
3) 按约定,函数名以Async结尾 比如: async Task MethodName(); async Task<bool> Method Name();
2. 在异步函数中,需要包含await关键字
3. await 关键字:
函数遇到await关键字后会挂起当前函数,然后返回上一级调用函数, 直到await 后面的语句返回task or Task<T>, 然后继续await下面的语句。
http://msdn.microsoft.com/zh-cn/library/hh156528.aspx
接下来的几个典型场景,让我逐步了解这2个关键字的特性
1. 典型的异步调用
从输出结果可以看到, 异步方法在遇到了await关键字后, 会立即返回被调用函数(如在DisplayAsync()中遇到await, 立即返回被调用testSimpleAsync函数并执行testSimpleAysnc后面的语句),然后等待await后面的语句返回并执行后面的操作。
注意到这里的DispalyAsync ends 和 testSimpleAsync complete 在不同的线程上,但这不是由于await关键字创建新的线程给await后面的语句,而是由于后面的语句本身会产生新的线程。 在这里,是Task.Delay(10);产生了新的线程, 参考:http://social.technet.microsoft.com/wiki/contents/articles/21177.visual-c-thread-sleep-vs-task-delay.aspx
2. 让多个任务并发
Task.Factory.StartNew会开启一个新的线程跑异步方法, 在循环中将所有DisplayAsync触发完成, Task.WhenAll等待所有方法完成在继续下个操作。
这里提下Task.Run() 和Task.Factory.StartNew, 实际上都是开启一个新的线程跑方法, 只是 Task.Factory.StartNew的可选参数更多,Task.Run()用的是默认参数:http://blogs.msdn.com/b/pfxteam/archive/2011/10/24/10229468.aspx
上面的这个方式,实际上用System.Threading.Tasks.Parallel.For也可以完成同样的效果。
3. 把一个异步方法转化成同步方法:
#1
#2
Task.wait会等待Task完成后再继续后面的语句,可以把异步的方法DisplayAsync()转换成同步方法,不同的,
#1会开启一个新的线程跑整个DisplayAsync()
#2会在同个线程中调用DisplayAsync.
这就是几个基本Await和Async使用,要用好这2个关键字,要更加深入的了解Task和Task相关的方法(Run. WhenAll,AnyAll, ContinueWith等), 以后有时间再研究下。
参考链接:
http://msdn.microsoft.com/zh-cn/library/hh873191.aspx
http://msdn.microsoft.com/zh-cn/library/hh191443.aspx
http://www.cnblogs.com/mgen/archive/2012/03/12/2392677.html
http://tomasp.net/blog/csharp-async-gotchas.aspx/
http://www.codeproject.com/Articles/127291/C-vNext-New-Asynchronous-Pattern
http://msdn.microsoft.com/zh-cn/library/hh873191.aspx
首先来了解些基本的概念:
1.
构建一个异步函数:
1) 申明时加入async 或Async 修饰符
2)返回值定义为 Task (普通函数中的void) 或 Task<T>(普通函数中的返回值)
3) 按约定,函数名以Async结尾 比如: async Task MethodName(); async Task<bool> Method Name();
2. 在异步函数中,需要包含await关键字
3. await 关键字:
函数遇到await关键字后会挂起当前函数,然后返回上一级调用函数, 直到await 后面的语句返回task or Task<T>, 然后继续await下面的语句。
http://msdn.microsoft.com/zh-cn/library/hh156528.aspx
接下来的几个典型场景,让我逐步了解这2个关键字的特性
1. 典型的异步调用
static void Main(string[] args) { Console.WriteLine("Thread {0} Main Function Starts", Thread.CurrentThread.ManagedThreadId); AsyncClass asyncClass = new AsyncClass(); asyncClass.testSimpleAsync(); Console.WriteLine("Thread {0} Main Function Ends \n", Thread.CurrentThread.ManagedThreadId); Thread.Sleep(Timeout.Infinite); }
/// 由于Main函数不能声明为异步方法,所以新建一个异步方法来调用目标异步方法 /// </summary> public async Task testSimpleAsync() { Console.WriteLine("\nThread {0} testSimpleAsync starts", Thread.CurrentThread.ManagedThreadId); Task displayCall = DisplayAsync(); Thread.Sleep(2); await displayCall; Console.WriteLine("Thread {0} testSimpleAsync complete \n", Thread.CurrentThread.ManagedThreadId); }
/// <summary> /// 目标异步方法 /// </summary> /// <returns></returns> private async Task DisplayAsync() { Console.WriteLine("\nThread {0} DisplayAsync starts", Thread.CurrentThread.ManagedThreadId); await Task.Delay(10); Console.WriteLine("Thread {0} DisplayAsync ends \n", Thread.CurrentThread.ManagedThreadId); }
从输出结果可以看到, 异步方法在遇到了await关键字后, 会立即返回被调用函数(如在DisplayAsync()中遇到await, 立即返回被调用testSimpleAsync函数并执行testSimpleAysnc后面的语句),然后等待await后面的语句返回并执行后面的操作。
注意到这里的DispalyAsync ends 和 testSimpleAsync complete 在不同的线程上,但这不是由于await关键字创建新的线程给await后面的语句,而是由于后面的语句本身会产生新的线程。 在这里,是Task.Delay(10);产生了新的线程, 参考:http://social.technet.microsoft.com/wiki/contents/articles/21177.visual-c-thread-sleep-vs-task-delay.aspx
2. 让多个任务并发
public async void testConcurrencyCall_NewThreadAsync() { Console.WriteLine("testConcurrencyCall_NewThread Start"); List<Task> lstTasks = new List<Task>(); for (int i = 2; i <= 5; i++) { Console.WriteLine("{0}: testConcurrencyCall_NewThread before starting new task cycle-{1}", Thread.CurrentThread.ManagedThreadId, i); Task task = Task.Factory.StartNew(() => DisplayAsync(i)); //DisplayAsync will run immediately at new thread. Console.WriteLine("{0}: testConcurrencyCall_NewThread after starting new task cycle-{1}", Thread.CurrentThread.ManagedThreadId, i); lstTasks.Add(task); } await Task.WhenAll(lstTasks);//Wait for all tasks complete. Console.WriteLine("testConcurrencyCall_NewThread complete \n"); } private async Task DisplayAsync(int i) { Console.WriteLine("{0}: {1}: cycle-{2}", Thread.CurrentThread.ManagedThreadId, "DisplayAsync starts", i); await Task.Delay(3000); Console.WriteLine("{0}: {1}: cycle-{2}", Thread.CurrentThread.ManagedThreadId, "DisplayAsync end", i); }
Task.Factory.StartNew会开启一个新的线程跑异步方法, 在循环中将所有DisplayAsync触发完成, Task.WhenAll等待所有方法完成在继续下个操作。
这里提下Task.Run() 和Task.Factory.StartNew, 实际上都是开启一个新的线程跑方法, 只是 Task.Factory.StartNew的可选参数更多,Task.Run()用的是默认参数:http://blogs.msdn.com/b/pfxteam/archive/2011/10/24/10229468.aspx
上面的这个方式,实际上用System.Threading.Tasks.Parallel.For也可以完成同样的效果。
3. 把一个异步方法转化成同步方法:
#1
public void convertAsSync() { Task task = Task.Run(() => DisplayAsync()); task.Wait(); }
#2
public void convertAsSync() { Task task = DisplayAsync(); task.Wait(); }
Task.wait会等待Task完成后再继续后面的语句,可以把异步的方法DisplayAsync()转换成同步方法,不同的,
#1会开启一个新的线程跑整个DisplayAsync()
#2会在同个线程中调用DisplayAsync.
这就是几个基本Await和Async使用,要用好这2个关键字,要更加深入的了解Task和Task相关的方法(Run. WhenAll,AnyAll, ContinueWith等), 以后有时间再研究下。
参考链接:
http://msdn.microsoft.com/zh-cn/library/hh873191.aspx
http://msdn.microsoft.com/zh-cn/library/hh191443.aspx
http://www.cnblogs.com/mgen/archive/2012/03/12/2392677.html
http://tomasp.net/blog/csharp-async-gotchas.aspx/
http://www.codeproject.com/Articles/127291/C-vNext-New-Asynchronous-Pattern
http://msdn.microsoft.com/zh-cn/library/hh873191.aspx
相关文章推荐
- async and await 的入门基础操作
- javascript异步编程的4种方法
- ASP XML编程objXML.async = False第1/2页
- .NET中的异步编程-EAP/APM使用方法及案例介绍
- Javascript异步编程的4种方法让你写出更出色的程序
- c#异步task示例分享(异步操作)
- .net4.5使用async和await异步编程实例
- javascript异步编程
- Android 复习_Task 与 Back Stack
- Android下Affinities和Task
- Linux进程状态解析之R、S、D、T、Z
- 事务管理 与异步TransactionManagement and async=true
- android的task与activity关系
- 构造awaitable对象
- 理解android中Activity和Task的关系
- 从小小题目逐步走进 JavaScript 异步调用
- 从不用 try-catch 实现的 async/await 语法说错误处理
- 从地狱到天堂,Node 回调向 async/await 转变
- 理解 JavaScript 的 async/await