ASP.NET 異步編程之Async await

本文重點介紹的是.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。

  • 請儘可能優先使用 Task<TResult> 和 Task 做爲異步方法的返回類型。

  • 用了await,方法必須使用async來修飾。

 

 參考文章:http://www.cnblogs.com/jesse2013/p/async-and-await.html   這裏介紹了異步的詳細發展史。

相關文章
相關標籤/搜索