日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

通過使用異步編程,可避免出現性能瓶頸,并提高應用程序的整體響應。然而,技術編寫異步應用程序的傳統方法過于復雜,這使得異步程序難以編寫,調試和維護。

Visual Studio2012引入了一個簡單的開發方法,異步編程,我們可以充分利用.NET Framework 4.5 和 Windows Runtime中對異步的支持。這項復雜的工作將會交由編譯器來搞定,開發人員就像是在使用同步代碼來編寫應用程序的邏輯結構,但其結果是,得到了所有異 步編程的優點,但只要付出一點點工作。

本主題簡要介紹何時以及如何使用異步編程,其中包括支持說明本主題的例子。由此下載VS2012.

異步提高響應能力

異步性必不可少,因為現實中有很多潛在的,可阻塞應用程序響應的情況,如當你的應用程序訪問網絡,文件系統等等。比如訪問Web資源,有時是緩慢的 或者是有延遲的。同步處理的話,如果有這樣的一個阻塞產生,那么整個應用程序就必須等待。而在一個異步的過程中,應用程序可以先繼續進行其他不依賴于網絡 的工作,直到所有可能產生阻塞的任務完成后再處理這些任務。

下表顯示了典型的可以通過異步編程提高響應的場景。列出的.NET Framework4.5和Windows Runtime的API包含支持異步編程的方法。

應用領域



支持異步方法的API



訪問Web



HttpClient , SyndicationClient



使用文件



StorageFile, StreamWriter, StreamReader,XmlReader



使用圖像



MediaCapture, BitmapEncoder, BitmapDecoder



WCF程序開發



Synchronous and Asynchronous Operations



使用sockets



Socket



異步性已經被證明對所有通過一個線程訪問UI,或是處理UI相關的活動的應用都特別的有價值。如果在同步的應用程序中任何一個處理過程被阻塞,那就意味著所有的東西都被阻塞了。你的應用程將會停止響應,更糟糕的是你可能會得出這樣的結論,這只是等待并不是失敗。

當你使用異步方法,應用程序將繼續響應的UI。您可以調整大小或最小化窗口,例如,當你不想等下去的時候,你可以關閉該應用程序。

現在這種基于異步的方法在你設計異步操作時,就像一組可以選擇的自動變速器,也就是說,你可以得到所有之前異步編程的好處,而不必像之前那樣苦逼(太讓人興奮了)。

異步方法現在很容易編寫

Async和Await關鍵字是C#異步編程的核心。通過使用這兩個關鍵字,你可以使用.NET Framework或Windows Runtime的資源創建一個異步方法如同你創建一個同步的方法一樣容易。通過使用async和await定義的異步方法,這里被稱為異步方法。

下面的例子顯示了一個異步方法。代碼中的幾乎所有的東西你看起來應該非常熟悉。注釋中描述了你為實現異步操作添加什么功能。

 1 // 在簽名中三個要注意的事項: 
 2 //  - 該方法具有一個async修飾符.  
 3 //  - 返回類型為 Task or Task<t>. (參考 "返回類型" 一節.)
 4 //    這里, 返回值是 Task<int> 因為返回的是一個整數類型. 
 5 //  - 這個方法的名稱以 "Async" 結尾.
 6 async Task<int> AccessTheWebAsync()
 7 { 
 8     // 你需要添加System.Net.Http的引用來聲明client
 9     HttpClient client = new HttpClient();
10 
11     // GetStringAsync 返回 Task<string>. 這意味著當Task結束等待之后 
12     // 你將得到一個string (urlContents).
13     Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
14 
15     // 你可以做一些不依賴于 GetStringAsync 返回值的操作.
16     DoIndependentWork();
17 
18     // await 操作掛起了當前方法AccessTheWebAsync. 
19     //  - AccessTheWebAsync 直到getStringTask完成后才會繼續. 
20     //  - 同時, 控制權將返回 AccessTheWebAsync 的調用者. 
21     //  - 控制權會在getStringTask完成后歸還到AccessTheAsync.  
22     //  - await操作將取回getStringTask中返回的string結果. 
23     string urlContents = await getStringTask;
24 
25     // return語句用來指定一個整數結果。
26     // 調用AccessTheWebAsync將會收到一個返回值的長度. 
27     return urlContents.Length;
28 }

如果AccessTheWebAsync沒有什么不依賴于GetStringAsync的內容,也可以直接調用如下代碼:

string urlContents = await client.GetStringAsync();

以下幾個特點總結了一下前面的例子中的異步方法。

方法中包含了 async 修飾符。

一個async方法按照慣例以“Async”結尾。

返回類型是如下類型之一:

Task<TResult> 當你的方法有返回值時,TResult即返回值的類型

Task 當你的方法沒有return語句,或者返回值并不參與任何形式的運算(包括賦值操作)。

Void 當你編寫一個異步事件處理時會用到

方法通常包括至少一個await的表達式,這意味著該方法在遇到await時不能繼續執行,直到等待異步操作完成。在此期間,該方法將被暫停,并且控制權返回到該方法的調用者。本主題接下來的部分說明了懸掛點后會發生什么。

在異步方法中,我們使用這些已經提供的關鍵字和類型來表達想要做什么的時候,編譯器并沒有閑著,他將處理包括跟蹤在暫停方法中控制權返回到 await點后將會如何處理。一些常規流程,如循環和異常處理,在之前的異步代碼中都比較難以處理。而現在都歸結到了一個async方法中,你會感覺你在 寫一個同步的代碼,之前的那些困惑已經不復存在了。

在異步方法中發生了什么

了解異步編程最重要的是理解控制權是如何在方法之間轉移的。下面的圖標將會解釋這個過程。

圖中的數字對應于下面的步驟。

1. 一個事件的處理函數用await的方式調用了異步方法 AccessTheWebAsync。

2. AccessTheWebAsync 創建了一個 HttpClient 實例,并調用了異步方法 GetStringAsync 來以下載一個頁面并將內容以string的形式返回.

3. 在GetStringAsync中將會碰到一些讓進程掛起的事情。也許它必須等待一個網站下載完成或其他一些阻塞性的動作,為了避免阻塞資源,GetStringAsync把控制權移交給了它的調用者AccessTheWEbAsync。

GetStringAsync返回Task<TResult>泛型,例子中的TResult是string類 型,AccessTheWebAsync將任務交給了getStringTask變量。這個任務代表了一個正在調用GetStringAsync的過程, 與一個承諾,當工作完成時,最終將產生string返回值。

4. 由于getStringTask并沒有被(用await)等待著索取結果,so AccessTheWebAsync 可以繼續其他不依賴于GetStringAsync最終返回結果的其他任務。這些任務由一個同步方法DoIndenpendentWork代表。

5.DoIndenpendentWork是一個同步方法,將會以同步的方式執行他的工作,并將返回值返回給調用者。

6. AccessTheWebAsync下一步是希望計算已經下載下來的字符長度,但是如果沒有這個字符,這個希望也就破滅了。

因此,AccessTheWebAsync 使用了await關鍵字掛起了自己的線程,并將控制權移交到了AccessTheWebAsync的調用者。AccessTheWebAsync將會返回 一個Task<int>給調用函數。這個任務承諾會在結束是返回給調用者一個int型的返回值。

注意

如果GetStringAsync在AccessTheWebAsync 調用await之前就已經完成了,那么控制權將依然在AccessTheWebAsync中。這種掛起和等待的操作也是很消耗資源的,如果返回值在 await之前就已經得到了,AccessTheWebAsync沒必要非得在用等待的方法去得到最終的結果。

在調用方法(這里是一個event的處理函數)的內部,處理過程是疊加的,event的處理函數將會等待AccessTheWebAsync,而 AccessTheWebAsync在等待GetStringAsync,與此同時,調用函數依然可以執行不依賴于這些返回值的操作。

7. GetStringAsync計算并產生一個string結果。這個string結果可能不是按照你現在期望的方式直接返回給他的調用函數,相反,這個結 果保存在一個代表方法完成的任務中,getStringTask。await操作符將會從getStringTask中取回期望的結果。賦值語句將會把結 果交給urlContents。

8. 當AccessTheWebAsync獲得了這個字符串結果,我們可以繼續計算這個字符串的長度了。這樣AccessTheWebAsync的工作也完成了,等待中的event處理函數也可以繼續了。

如果你剛剛接觸異步編程,那應該花一分鐘來思考一下同步行為和異步行為的不同。同步方法在工作完成之后返回(步驟5),但是異步方法返回一個 task值在他工作被暫停的時候(步驟3,6).當異步方法完成了他的工作之后,task被標記為complete,工作的結果也保存在task之中。

異步的API方法

你可能會想知道在哪里可以找到,如GetStringAsync,支持異步編程的API方法。.NET Framework 4.5包含許多使用await和async工作的成員方法。識別這些方法很簡單,方法名都是以”Async”結尾的并且返回類型都是Task或者 Task<TResult>。例如,System.IO.Stream類包含的方法,如CopyToAsync,ReadAsync,及 WriteAsync的對應的同步方法是CopyTo,Read和Write。

線程

異步方法的目的是不阻塞操作。在async方法中, await任務在執行的過程中,并不會阻塞當前的線程,其余的方法可以繼續執行,控制權將會移交到async方法的調用者。

async和await關鍵字并不會創建額外的線程,async方法不會去請求多線程操作。真正創建線程的操作是由Task.Run()實現的,一個async方法并不是在他自己的線程上執行的,只有當方法被激活時,才會使用當前線程的上下文和處理時間。

async方法要比BackgroundWorker更實用,而且使用起來更簡單而且不用去過多的考慮競態沖突神馬的。async方法會將運行中的代碼依據某些算法進行合理的拆分,并傳遞給線程池,這也是BackgroundWorker不能比的。

Async和Await

如果需要使用async或者await指定一個異步方法,我們需要注意一下兩點:

用async標記的異步方應該使用await關鍵子來制定掛起點。await操作符會告訴編譯器,這個async方放在完成之前,后面的代碼無法繼續執行,同時,控制權轉移到async方法的調用者。

標記為async的方法,調用時應使用await。

一個async方法里通常包含一個或多個的對應的await操作符,但如果沒有await表達式也不會導致編譯錯誤。但如果調用一個async方 法,卻不使用await關鍵字來標記一個掛起點的話,程序將會忽略async關鍵字并以同步的方式執行。編譯器會對類似的問題發出警告。

async和await都是上下文關鍵字:更多的細節可以參考:

Async (Visual Basic)

async (C# Reference)

Await Operator (Visual Basic)

await (C# Reference)

返回類型和參數

在.NET Framework編程中,一個async方法通常返回的類型是Task或者Task<TResult>。在異步方法中,await操作符作用于從另外一個異步方法返回的Task。

如果指定Task<TResult>為返回結果,那么這個方法必須包含return指定的TResult結果的語句。

如果使用Task作為返回值,那么這個方法應該不存在使用return語句返回結果的代碼,或者返回的結果不參與任何運算(包括賦值操作)。

 1 // 明確指定 Task<tresult>
 2 async Task<int> TaskOfTResult_MethodAsync()
 3 {
 4     int hours;
 5     // . . .
 6     // return一個整數作為結果.
 7     return hours;
 8 }
 9 
10 // 調用 TaskOfTResult_MethodAsync
11 Task<int> returnedTaskTResult = TaskOfTResult_MethodAsync();
12 int intResult = await returnedTaskTResult;
13 // 或者使用一條語句
14 int intResult = await TaskOfTResult_MethodAsync();
15 
16 
17 // 明確指定 Task
18 async Task Task_MethodAsync()
19 {
20     // . . .
21     // 方法沒有任何return語句.  
22 }
23 
24 // 調用 Task_MethodAsync
25 Task returnedTask = Task_MethodAsync();
26 await returnedTask;
27 // 或者使用一條語句
28 await Task_MethodAsync();

每一個返回的task都代表一個正在執行的工作,task包裝的信息中包含了這個異步方法的執行時的狀態,最終的結果,或者處理過程中拋出的異常。

如果返回值為void,這種類型主要使用于定義事件處理。異步事件通常被認為是一系列異步操作的開始。使用void返回類型不需要await,而且調用void異步方法的函數不會捕獲方法拋出的異常。

另外,async方法不能使用ref或者out參數,但是可以調用含有這些參數的方法。

命名約定

按照約定,你應該在異步方法的名稱后面追加“Async”用以標記此方法。但是在event,基類和接口中不需要遵守約定,就像本文例子中event處理函數Button1_Click一樣。

相關主題

一個完整的例子

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using System.Windows;
 7 using System.Windows.Controls;
 8 using System.Windows.Data;
 9 using System.Windows.Documents;
10 using System.Windows.Input;
11 using System.Windows.Media;
12 using System.Windows.Media.Imaging;
13 using System.Windows.Navigation;
14 using System.Windows.Shapes;
15 
16  
17 using System.Net.Http;
18 
19 namespace AsyncFirstExample
20 {
21     public partial class MainWindow : Window
22     {
23         // 將event處理函數用async標記,這樣就可以在處理函數中使用await實現異步操作. 
24         private async void StartButton_Click(object sender, RoutedEventArgs e)
25         {
26             // 調用和await分離的方式. 
27             //Task<int> getLengthTask = AccessTheWebAsync(); 
28             //// 在這里做一些其他的工作. 
29             //int contentLength = await getLengthTask; 
30 
31             int contentLength = await AccessTheWebAsync();
32 
33             resultsTextBox.Text +=
34                 String.Format("\r\nLength of the downloaded string: {0}.\r\n", contentLength);
35         }
36 
37 
38            // 在簽名中三個要注意的事項: 
39     //  - 該方法具有一個async修飾符.  
40     //  - 返回類型為 Task or Task<t>. (參考 "返回類型" 一節.)
41     //    這里, 返回值是 Task<int> 因為返回的是一個整數類型. 
42     //  - 這個方法的名稱以 "Async" 結尾.
43     async Task<int> AccessTheWebAsync()
44     { 
45             // 你需要添加System.Net.Http的引用來聲明client
46             HttpClient client = new HttpClient();
47 
48             // GetStringAsync 返回 Task<string>. 這意味著當Task結束等待之后 
49             // 你將得到一個string (urlContents).
50             Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
51 
52             // 你可以做一些不依賴于 GetStringAsync 返回值的操作.
53             DoIndependentWork();
54 
55             // await 操作掛起了當前方法AccessTheWebAsync. 
56             //  - AccessTheWebAsync 直到getStringTask完成后才會繼續. 
57             //  - 同時, 控制權將返回 AccessTheWebAsync 的調用者. 
58             //  - 控制權會在getStringTask完成后歸還到AccessTheAsync.  
59             //  - await操作將取回getStringTask中返回的string結果. 
60             string urlContents = await getStringTask;
61 
62             // return語句用來指定一個整數結果。
63             // 調用AccessTheWebAsync將會收到一個返回值的長度. 
64             return urlContents.Length;
65     }
66 
67 
68         void DoIndependentWork()
69         {
70             resultsTextBox.Text += "Working . . . . . . .\r\n";
71         }
72     }
73 }
74 
75 // 運行結果: 
76 
77 // Working . . . . . . . 
78 
79 // Length of the downloaded string: 41564.

分享到:
標簽:如何使用 編程 4.5 net Async
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定