.NET4.5新特性async和await修飾符實現異步編程

開篇

每個版本的.net都會引入一些新的特性,這些特性方便開發人員可以快速實現一些功能。雖然.net版本一直在更新,可是新版本對舊版本的程序都是兼容的,在這一點上微軟作的仍是很是好的。每次學一個新內容,第一次接觸的方法在腦海裏佔的位置仍是比較重要的,從剛開始接觸.net的多線程編程是使用Thread類,而後後面寫的程序只要用到異步或者多線程就立刻會想到用Thread,雖然知道委託的異步調用也可以實現,可是腦海裏面的排在前面仍是Thread類,在那個時候不知道他們之間的區別和優劣,也就不懂得如何去取捨。到了.net4.0引入了Task這個任務類,讓咱們用少許的代碼就開始實現了多線程編程,從這個時候開始我也慢慢的瞭解了.net裏面的有哪一些異步實現的方式以及多線程內部的一些機制,也知道它們各自的優點。在接觸Task類的時候.net4.5也發佈出來了,而且帶來一個更加方便的關鍵字(async,await),輕鬆實現函數異步調用。雖然知道async和await修飾符,可是本身卻遲遲沒有接觸,由於日常的工做中使用Task類就基本能實現我想要的效果。最近看了一些源碼,源碼中有不少代碼是應用了async和await的關鍵字來實現異步的,因此我也不得不去學習,接觸以後發現,使用async和await關鍵字確實簡化了之前異步編程所須要的步驟,也比較好理解。下面經過一些小例子來簡述async和await修飾符如何實現異步編程以及和之前使用Task類來實現異步編程的少量區別。另外,關於.net4.0(包含)之前的的異步編程模式能夠參考個人另一篇博文:http://www.cnblogs.com/mingjiatang/p/5267391.htmlhtml

1 async和await實現方法異步調用

下面看一段由async定義的異步方法以及異步方法的調用代碼,以下:
 
        static  void Main(string[] args)
        {
            AsyncMethod(10);//no.1
            Console.WriteLine("執行其餘的東西,當前線程id:{0}", Thread.CurrentThread.ManagedThreadId);//out.4
            Console.ReadKey();

        }

        static async void  AsyncMethod(int i)
        {
            Console.WriteLine("異步方法開始,當前線程id:{0}",Thread.CurrentThread.ManagedThreadId);//out.1
            await AsyncTaskMethod(i);//no.3
            Console.WriteLine("異步方法退出,當前線程id:{0}", Thread.CurrentThread.ManagedThreadId);////out.6
        }

        public static  async Task<int> AsyncTaskMethod(int i)
        {
            Console.WriteLine("【任務】開始,當前線程id:{0}", Thread.CurrentThread.ManagedThreadId);//out.2
            Task<int> t = Task.Run(() =>
            {

                Console.WriteLine("【任務】正在執行,執行任務的線程id:{0}", i, Thread.CurrentThread.ManagedThreadId);//out.3
                Thread.Sleep(2000);
                return i;
            });//no.4
            
            int r= await t;//no.5
            Console.WriteLine("【任務】執行完成,當前線程id:{0}", i, Thread.CurrentThread.ManagedThreadId);//out.5
            return r;
        }

下面是執行結果:編程

 
----------------async和await的語法使用結合代碼--------------------
 
在解釋程序的執行原理以前,先介紹一下async和await關鍵的語法,async只能修飾方法和lambda表達式或者匿名方法,await一般應用於Task或Task<TResult>對象前,用於等待任務完成。
 
-----------------解釋程序的執行過程-----------------------------------
 
一、主線程【9】進入Main方法,執行no.1異步方法。
二、主線程【9】進入異步方法AsyncMethod內部,執行out.1。
三、主線程【9】執行no.3異步任務方法,因爲no.3表達式前面await關鍵字修飾,因此要等待任務完成以後纔會執行out.6。
四、主線程【9】進入異步任務方法AsyncTaskMethod內部,執行out2。
五、開始執行Task任務,程序從線程池中獲取一個任務線程【10】執行no.4的任務。
六、任務線程【10】開始任務,執行out.3;
七、在線程【10】執行任務的同時,主線程【9】同步運行,當執行到no.5時,遇到await關鍵字,會一直等待任務的完成,不會再執行下面的out.5,所以主線往上返回Main方法中,執行out.4,到此,主線程的代碼執行完畢。
八、任務線程【10】執行任務完成,而後再執行no.5後面的代碼out.5,最後返回任務執行的結果。
九、這時no.3一直等待的任務已經執行完畢,再從線程池中開啓一個線程【6】調用no.3以後的代碼。
十、到此整個程序就執行完畢了。

小結

其實在async和await關鍵字的異步實現依然是使用線程池中的線程。我的認爲,內部是使用Task類實現的,只是在任務結束時的回調比單獨使用Task要簡單一些。單獨使用Task類實現異步時,當任務完成要進行回調,須要對Task對象調用ContinueWith方法,綁定任務結束後的回調函數並傳遞相關參數。而使用async和await實現異步時,只須要使用Task去執行任務,而後用await去等待任務執行的結果就行了,並不會阻塞主線程的運行,整個編碼過程和同步實現差很少,這個例子就是一個很好的說明。
 
--------------------------------最後再說明一下async和await使用要點和做用------------------------------------------
一、異步的方法(包括匿名方法,和lambda表達式)必需要使用async修飾
二、異步方法能夠具備返回類型的 void,  Task,或 Task< TResult> 。該方法不能聲明任何 ref 或 出參數,儘管它能夠調用具備此類參數的方法。其中返回值爲TRsult時,返回類型就是 Task< TResult>。
三、await 運算符應用於一個異步方法的任務掛起方法的執行,直到等待任務完成。  任務表示正在進行的工做。
四、await 表達式不阻止調用它的線程。   當任務完成時,將會調用其延續任務,而且,異步方法的執行恢復它將會中止的位置。換句話說就是:await會讓當前方法等待Task執行完畢再執行。
相關文章
相關標籤/搜索