本文重點介紹的是.NET Framework4.5 推出的異步編程方案 async awaithtml
請先看個5分鐘的微軟演示的視頻:
視頻地址: https://channel9.msdn.com/Blogs/ASP-NET-Site-Videos/async-and-await數據庫
網絡上已經有不少文章介紹了這個技術點的應用方式,可是舉的例子都是.NET 自帶提供的系統異步方法編程
因此有些同窗就看不大懂,若是是非系統自帶的,如何實現異步。json
實際上,有時候一點就能通,把異步的本質瞭解明白了,也就懂了。網絡
異步編程的本質就是 新開任務線程來處理異步
這個如何理解呢,請看下文介紹異步編程發展史async
static void Main(){ new Thread(Go).Start(); // .NET 1.0開始就有的 Task.Factory.StartNew(Go); // .NET 4.0 引入了 TPL Task.Run(new Action(Go)); // .NET 4.5 新增了一個Run的方法 }
這裏你們不難看出,.NET 4.5以後引入了 Task.Run方法,實際上呢,異步編程就是經過這個實現的。ide
瞭解線程的人也知道,新開一個線程來處理事務,這個很常見,可是在以往,是沒辦法接收線程裏面返回的值的。異步編程
因此這時候就該 await 出場了學習
await,從字面意思,不難理解,就是等待的意思。
執行await的方法必須是async修飾的,而且是Task的類型。 異步執行後,返回的信息存儲在result屬性中。
但並不是主進程就會卡在await行的代碼上,執行到await方法以後,主線程繼續往下執行,無需等待新的線程執行完再繼續。
當須要用到新線程返回的result結果時,此時主進程纔會等待新線程執行完並返回內容。
也就會說,若無需用到新線程返回的結果,那麼主進程不會等待。
async 和await呢,返回類型就3種,void,Task,Task<TResult>
一、void
若是在觸發後,你懶得管,請使用 void。
void 返回類型主要用在事件處理程序中,一種稱爲「fire and forget」(觸發並忘記)的活動的方法。除了它以外,咱們都應該儘量是用 Task,做爲咱們異步方法的返回值。
返回 void,意味着不能 await 該異步方法,便可能出現線程阻塞,而且也沒法獲取 exception,拋出的異常,一般這些異常會致使咱們的程序失敗,若是你使用的是 Task 和 Task<Result>,catch 到的異常會包裝在屬性裏面,調用方法就能夠從中獲取異常信息,並選擇正確的處理方式。
二、Task
你若是隻是想知道執行的狀態,而不須要一個具體的返回結果時,請使用 Task
與void對比呢,是Task可使用await進行等待新線程執行完畢。而void不須要等待。
三、Task<TResult>
當你添加 async 關鍵字後,須要返回一個將用於後續操做的對象,請使用 Task<TResult>。
主要有兩種方式獲取結果值,一個是使用 Result 屬性,一個是使用 await。他們的區別在於:若是你使用的是 Result,它帶有阻塞性。即在任務完成以前進行訪問讀取它,當前處於活動狀態的線程都會出現阻塞的情形,一直到結果值可用。因此,在絕大多數狀況下,除非你有絕對的理由告訴本身,不然都應該使用 await,而不是屬性 Result 來讀取結果值。
下面咱們直接看一些代碼就懂了:
/// <summary> /// 添加多條 /// </summary> /// <param name="list"></param> /// <returns></returns> public virtual bool Add(IEnumerable<T> list) { CreateDataBase();//建立數據庫鏈接 foreach (T t in list) { this.Add(t); } return true; } public virtual async Task<bool> AddAsync(IEnumerable<T> list) { return await Task.Run(() => this.Add(list)); }
正常狀況下,咱們約定,異步的方法名均以Async結尾。
如下是服務層調用
/// <summary> /// 日誌的json格式字符串 包含 title,url,level,descript /// </summary> /// <param name="content"></param> /// <returns></returns> public async Task<bool> AddAsync(string content) { using (var mongoDbContext = new Log.DAL.DbContext()) { if (!string.IsNullOrWhiteSpace(content)) { Log.Model.Record model = Newtonsoft.Json.JsonConvert.DeserializeObject<Log.Model.Record>(content); model.AddTime = DateTime.Now; var result = await mongoDbContext.Record.AddAsync(model); return result; } else { return false; } } }
再接着,進行控制器中的調用
public async Task<ActionResult> Add(string content) { var flag = await new Log.Service.RecordService().AddAsync(content); ; return View(); }
下面的代碼呢,咱們演示一下何時須要用到result屬性
//不須要,由於用了await public async Task<ActionResult> Detail(int id) { var model = await new DbContext().Record.FirstOrDefaultAsync(m => m.ID == id); return View(model); } //須要 public async Task<ActionResult> Detail(int id) { var model = new DbContext().Record.FirstOrDefaultAsync(m => m.ID == id).Result; return View(model); }
這樣,咱們異步編程就講解完了。本文主要是講解異步是實質,學習這個須要異步有必定的學習和了解。
總結:
當你添加 async 關鍵字後,須要返回一個將用於後續操做的對象,請使用 Task<TResult>;
你若是隻是想知道執行的狀態,而不須要知道具體的返回結果時,請使用 Task;
若是在觸發後,你懶得管,請使用 void。
參考文章:http://www.cnblogs.com/jesse2013/p/async-and-await.html 這裏介紹了異步的詳細發展史。