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

来源:http://www.cnblogs.com/mingjiatang/archive/2016/07/29/5719260.html
-Advertisement-
Play Games

開篇 每一個版本的.net都會引入一些新的特性,這些特性方便開發人員能夠快速實現一些功能。雖然.net版本一直在更新,但是新版本對舊版本的程式都是相容的,在這一點上微軟做的還是非常好的。每次學一個新內容,第一次接觸的方法在腦海裡占的位置還是比較重要的,從剛開始接觸.net的多線程編程是使用Threa ...


開篇

每一個版本的.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.html

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>對象前,用於等待任務完成。   -----------------解釋程式的執行過程-----------------------------------   1、主線程【9】進入Main方法,執行no.1非同步方法。 2、主線程【9】進入非同步方法AsyncMethod內部,執行out.1。 3、主線程【9】執行no.3非同步任務方法,由於no.3表達式前面await關鍵字修飾,所以要等待任務完成之後才會執行out.6。 4、主線程【9】進入非同步任務方法AsyncTaskMethod內部,執行out2。 5、開始執行Task任務,程式從線程池中獲取一個任務線程【10】執行no.4的任務。 6、任務線程【10】開始任務,執行out.3; 7、線上程【10】執行任務的同時,主線程【9】同步運行,當執行到no.5時,遇到await關鍵字,會一直等待任務的完成,不會再執行下麵的out.5,因此主線往上返回Main方法中,執行out.4,到此,主線程的代碼執行完畢。 8、任務線程【10】執行任務完成,然後再執行no.5後面的代碼out.5,最後返回任務執行的結果。 9、這時no.3一直等待的任務已經執行完畢,再從線程池中開啟一個線程【6】調用no.3之後的代碼。 10、到此整個程式就執行完畢了。

小結

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

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1. Freemarker是一個 "模板引擎" ,在.NET中有類似的T4模板,FreeMarker對ASP.NET MVC也很友好, "鏈接地址" ,引用官方的一幅圖 模板+數據=視圖 Following are the topics including in this chapter: Demo ...
  • 目錄索引 【無私分享:ASP.NET CORE 項目實戰】目錄索引 簡介 本章我們來介紹下Asp.net Core 使用 CodeFirst 創建資料庫和表 修改EF上下文對象,添加測試類 我修改了一下名字,Domains 改為了 wkmvc.Data 我們新建一個文件夾 Models 用於存放 模 ...
  • 這兩天發現一個model binding中的坑,就是action中的參數名不能和屬性重覆,否則綁定不了,參數始終是null, 舉例說明: T_Account類定義如下 在Edit視圖提交時的處理方法定義 註意此時Include中有Account屬性,參數名也叫account, account始終為n ...
  • 這個系列是,基礎學習系列的最後一部分,這裡,我打算翻譯一篇國外的技術文章結束這個基礎部分的學習;後面打算繼續寫深入學習MVC系列的文章,之所以要寫博客,我個人覺得,做技術的,首先得要懂得分享,說不定你自己以為正確的東西,存在瑕疵,分享出來,大家也可以互相進步。這樣整個生態圈也會越來越好。不是麽? 好 ...
  • rows 是客戶端傳過來的行數,page是頁碼,傳參就需要就兩個參數就行,sql語句中_row 和_page 自己聲明的局部變數,值還是相應的row 和page ,為了運算而已。 用資料庫類獲得它的DataTable,轉換為json格式通過一般處理程式傳到客戶端,客戶端顯示就ok了。這裡我使用的是e ...
  • 說明:本文是個人翻譯文章,由於個人水平有限,有不對的地方請大家幫忙更正。 原文: "dotnet restore" 翻譯: "dotnet restore" 名稱 還原一個項目的依賴項和工具 概要 `dotnet restore [ source] [ packages] [ disable par ...
  • ...
  • 寫這點東西主要是看到知乎上有人在討論相關的問題,但是有不少人都在說一些不嚴謹,甚至是完全錯誤 但是流傳甚廣的東西,甚至是一些大神都在說,以下根據我的回答總結。 一個很常見又很低級的誤區是:認為引用類型保存在堆上,值類型保存在棧上……其實這個問題幼稚得我懶得說……但是實在又忍不住吐槽。 很多人都在說這 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...