亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

.NET基于任務的異步模式(Task-basedAsynchronousPattern,TAP)asyncawait

2019-11-14 16:04:50
字體:
來源:轉載
供稿:網友

本文內容

  • 概述
  • 編寫異步方法
  • 異步程序中的控制流
  • API 異步方法
  • 線程
  • 異步和等待
  • 返回類型和參數
  • 參考資料

下載 Demo

下載 Demo TPL 與 APM 和 EAP 結合(APM 和 EAP 這兩個標準異步方式已經不能適應多核時代,但之前用這兩種方式寫的代碼怎么辦?——把它們改造一下,跟 TPL 結合)

概述


異步對可能起阻止作用的活動(例如,應用程序訪問 Web 時)至關重要。 對 Web 資源的訪問有時很慢或會延遲。 如果此類活動在同步過程中受阻,則整個應用程序必須等待。在異步過程中,應用程序可繼續執行不依賴 Web 資源的其他工作,直至潛在阻止任務完成。

下表是利用異步編程能提高響應能力的典型場景。從 .NET Framework 4.5 和 Windows 運行時中列出的 API 包含支持異步編程的方法。

應用程序區域

包含異步方法的受支持的 API

Web 訪問

HttpClient ,SyndicationClient

使用文件

StorageFile、StreamWriter、StreamReader、xmlReader

使用圖像

MediaCapture、BitmapEncoder、BitmapDecoder

WCF 編程

同步和異步操作

由于所有與用戶界面相關的活動通常共享一個線程,因此,異步對訪問 UI 線程的應用程序來說尤為重要。如果任何進程在同步應用程序中受阻,則所有進程都將受阻。 你的應用程序停止響應,因此,你可能在其等待過程中認為它已經失敗。

使用異步方法時,應用程序將繼續響應 UI。 例如,你可以調整窗口的大小或最小化窗口;如果你不希望等待應用程序結束,則可以將其關閉。

可以使用三種方式來實現 TAP:即手動使用 C# 編譯器,或將編譯器和手動方法結合使用。使用 TAP 模式來實現計算密集型和 I/O 密集型異步操作。

  • 使用編譯器。在 Visual Studio 2012 和 .NET Framework 4.5 中,任何具有 async 關鍵字的方法都被看作是一種異步方法,并且 C# 會執行必要的轉換,以通過 TAP 來異步實現該方法。 異步方法應返回 System.Threading.Tasks.Task 或 System.Threading.Tasks.Task<TResult> 對象。
  • 手動生成 TAP 方法。也可以手動實現 TAP 模式,以更好地控制實現。編譯器依賴從 System.Threading.Tasks 命名空間公開的公共外圍應用和 System.Runtime.CompilerServices 命名空間中支持的類型。 如要自己實現 TAP,你需要創建一個 TaskCompletionSource<TResult> 對象、執行異步操作,并在操作完成時,調用 SetResult、SetException、SetCanceled 方法,或調用這些方法之一的Try版本。 手動實現 TAP 方法時,需在所表示的異步操作完成時完成生成的任務。 例如:
  • public static Task<int> ReadTask(this Stream stream, byte[] buffer, int offset, int count, object state)
    {
        var tcs = new TaskCompletionSource<int>();
        stream.BeginRead(buffer, offset, count, ar =>
        {
            try { tcs.SetResult(stream.EndRead(ar)); }
            catch (Exception exc) { tcs.SetException(exc); }
        }, state);
        return tcs.Task;
    }
  • 混合方法。你可能發現手動實現 TAP 模式、但將實現核心邏輯委托給編譯器的這種方法很有用。 例如,當你想要驗證編譯器生成的異步方法之外的實參時,可能需要使用這種混合方法,以便異??梢赞D義到該方法的直接調用方而不是通過 System.Threading.Tasks.Task 對象被公開:
  • public Task<int> MethodAsync(string input)
    {
        if (input == null) throw new ArgumentNullException("input");
        return MethodAsyncInternal(input);
    }
     
    PRivate async Task<int> MethodAsyncInternal(string input)
    {
     
       // code that uses await goes here
     
       return value;
    }

本文主要說明“使用編譯器”方法。

編寫異步方法


C# 中 asyncawait 關鍵字是異步編程的核心。通過這兩個關鍵字就可以輕松創建異步方法,幾乎與創建同步方法一樣。如下所示的 WPF 程序,布局文件上有個按鈕和文本框:

private async void StartButton_Click(object sender, RoutedEventArgs e)
{
    // Call and await separately.
    //Task<int> getLengthTask = accessTheWebAsync();
    //// You can do independent work here.
    //int contentLength = await getLengthTask;
 
    int contentLength = await AccessTheWebAsync();
 
    resultsTextBox.Text +=
        String.Format("/r/nLength of the downloaded string: {0}./r/n", contentLength);
}
 
 
// Three things to note in the signature:
//  - The method has an async modifier. 
//  - The return type is Task or Task<T>. (See "Return Types" section.)
//    Here, it is Task<int> because the return statement returns an integer.
//  - The method name ends in "Async."
async Task<int> AccessTheWebAsync()
{ 
    // You need to add a reference to System.Net.Http to declare client.
    HttpClient client = new HttpClient();
 
    // GetStringAsync returns a Task<string>. That means that when you await the
    // task you'll get a string (urlContents).
    Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
 
    // You can do work here that doesn't rely on the string from GetStringAsync.
    DoIndependentWork();
 
    // The await Operator suspends AccessTheWebAsync.
    //  - AccessTheWebAsync can't continue until getStringTask is complete.
    //  - Meanwhile, control returns to the caller of AccessTheWebAsync.
    //  - Control resumes here when getStringTask is complete. 
    //  - The await operator then retrieves the string result from getStringTask.
    string urlContents = await getStringTask;
 
    // The return statement specifies an integer result.
    // Any methods that are awaiting AccessTheWebAsync retrieve the length value.
    return urlContents.Length;
}
 
 
void DoIndependentWork()
{
    resultsTextBox.Text += "Working . . . . . . ./r/n";
}

執行結果:

Working . . . . . . .
 
Length of the downloaded string: 41609.

說明:

1,當程序訪問網絡時,無論你如何拖拽、最大化最小化、如何點擊,UI 都不會失去響應;

2,“async Task<int> AccessTheWebAsync()”方法簽名,有三點需要注意:1)有 async 修飾符;2)返回類型是 TaskTask<int>。該方法是 Task<int>,因為它返回的是鏈接內容的大??;3)方法名以 Async 結尾;

3,“string urlContents = await getStringTask;”語句,有四點需要注意:1)AccessTheWebAsync 方法直到 getStringTask 完成才能繼續;2)同時,控制流返回到 AccessTheWebAsync 的調用者;3)getStringTask 完成后,控制流才會恢復;4)之后,await 操作符從 getStringTask 檢索結果。

下面總結讓一個示例成為異步方法的特征:

  • 方法簽名包含一個 async 修飾符。
  • 按照約定,異步方法的名稱以“Async”后綴結尾。
  • 返回類型為下列類型之一:
    • 如果你的方法有 TResult 類型的返回語句,則為 Task<TResult>。
    • 如果你的方法沒有返回語句,則為 Task。
    • 如果你編寫的是異步事件處理程序,則為 Void(Visual Basic 中為 Sub)。
  • 方法通常包含至少一個 await 表達式,該表達式標記一個點,在該點上,直到等待的異步操作完成方法才能繼續。同時,將方法掛起,并且控件返回到方法的調用方。

在異步方法中,可使用提供的關鍵字和類型來指示需要完成的操作,且編譯器會完成其余操作,其中包括持續跟蹤控件以掛起方法返回等待點時發生的情況。 一些常規流程(例如,循環和異常處理)在傳統異步代碼中處理起來可能很困難。 在異步方法中,元素的編寫頻率與同步解決方案相同且此問題得到解決。

異步程序中的控制流


異步編程中最需弄清的是控制流是如何從方法移動到方法。

private async void StartButton_Click(object sender, RoutedEventArgs e)
       {
           // Call and await separately.
           //Task<int> getLengthTask = AccessTheWebAsync();
           //// You can do independent work here.
           //int contentLength = await getLengthTask;
           resultsTextBox.Text += "1:  Entering startButton_Click./r/n" +
               "           Calling AccessTheWebAsync./r/n";
 
           int contentLength = await AccessTheWebAsync();
 
           resultsTextBox.Text +=
               String.Format("/r/n6:   Length of the downloaded string: {0}./r/n", contentLength);
       }
 
       async Task<int> AccessTheWebAsync()
       {
           resultsTextBox.Text += "/r/n2:  Entering AccessTheWebAsync.";
 
           HttpClient client = new HttpClient();
 
           resultsTextBox.Text += "/r/n        Calling HttpClient.GetStringAsync./r/n";
 
           Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
 
           DoIndependentWork();
 
           resultsTextBox.Text += "/r/n4:  Back in startButton_Click./r/n" +
               "       Task getStringTask is started./r/n";
           string urlContents = await getStringTask;
 
           resultsTextBox.Text += "/r/n5:  Back in AccessTheWebAsync." +
               "/r/n       Task getStringTask is complete." +
               "/r/n       Processing the return statement." +
               "/r/n       Exiting from AccessTheWebAsync./r/n";
 
           return urlContents.Length;
       }
 
 
       void DoIndependentWork()
       {
           resultsTextBox.Text += "/r/n3:  Entering DoIndependentWork./r/n";
 
           resultsTextBox.Text += "/r/n        Working . . . . . . ./r/n";
       }

運行結果:

1:  Entering startButton_Click.
           Calling AccessTheWebAsync.
 
2:  Entering AccessTheWebAsync.
        Calling HttpClient.GetStringAsync.
 
3:  Entering DoIndependentWork.
 
        Working . . . . . . .
 
4:  Back in startButton_Click.
       Task getStringTask is started.
 
5:  Back in AccessTheWebAsync.
       Task getStringTask is complete.
       Processing the return statement.
       Exiting from AccessTheWebAsync.
 
6:   Length of the downloaded string: 41609.

再稍微復雜點:

private async void startButton_Click(object sender, RoutedEventArgs e)
       {
           // The display lines in the example lead you through the control shifts.
           resultsTextBox.Text += "ONE:   Entering startButton_Click./r/n" +
               "           Calling AccessTheWebAsync./r/n";
 
           Task<int> getLengthTask = AccessTheWebAsync();
 
           resultsTextBox.Text += "/r/nFOUR:  Back in startButton_Click./r/n" +
               "           Task getLengthTask is started./r/n" +
               "           About to await getLengthTask -- no caller to return to./r/n";
 
           int contentLength = await getLengthTask;
 
           resultsTextBox.Text += "/r/nSIX:   Back in startButton_Click./r/n" +
               "           Task getLengthTask is finished./r/n" +
               "           Result from AccessTheWebAsync is stored in contentLength./r/n" +
               "           About to display contentLength and exit./r/n";
 
           resultsTextBox.Text +=
               String.Format("/r/nLength of the downloaded string: {0}./r/n", contentLength);
       }
 
       async Task<int> AccessTheWebAsync()
       {
           resultsTextBox.Text += "/r/nTWO:   Entering AccessTheWebAsync.";
 
           // Declare an HttpClient object and increase the buffer size. The default
           // buffer size is 65,536.
           HttpClient client =
               new HttpClient() { MaxResponseContentBufferSize = 1000000 };
 
           resultsTextBox.Text += "/r/n           Calling HttpClient.GetStringAsync./r/n";
 
           // GetStringAsync returns a Task<string>. 
           Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
 
           resultsTextBox.Text += "/r/nTHREE: Back in AccessTheWebAsync./r/n" +
               "           Task getStringTask is started.";
 
           // AccessTheWebAsync can continue to work until getStringTask is awaited.
 
           resultsTextBox.Text +=
               "/r/n           About to await getStringTask and return a Task<int> to startButton_Click./r/n";
 
           // Retrieve the website contents when task is complete.
           string urlContents = await getStringTask;
 
           resultsTextBox.Text += "/r/nFIVE:  Back in AccessTheWebAsync." +
               "/r/n           Task getStringTask is complete." +
               "/r/n           Processing the return statement." +
               "/r/n           Exiting from AccessTheWebAsync./r/n";
 
           return urlContents.Length;
       }

運行結果:

ONE:   Entering startButton_Click.
           Calling AccessTheWebAsync.
 
TWO:   Entering AccessTheWebAsync.
           Calling HttpClient.GetStringAsync.
 
THREE: Back in AccessTheWebAsync.
           Task getStringTask is started.
           About to await getStringTask and return a Task<;int> to startButton_Click.
 
FOUR:  Back in startButton_Click.
           Task getLengthTask is started.
           About to await getLengthTask -- no caller to return to.
 
FIVE:  Back in AccessTheWebAsync.
           Task getStringTask is complete.
           Processing the return statement.
           Exiting from AccessTheWebAsync.
 
SIX:   Back in startButton_Click.
           Task getLengthTask is finished.
           Result from AccessTheWebAsync is stored in contentLength.
           About to display contentLength and exit.
 
Length of the downloaded string: 41635.

API 異步方法


如何找到像 GetStringAsync 這樣支持異步編程的方法。 .NET Framework 4.5 包含使用 async 和 await 的許多成員,它們都已“Async”為后綴和 Task 或 Task<TResult> 的返回類型。 例如,System.IO.Stream 類包含的方法 CopyToAsync、ReadAsync、WriteAsync 等方法以及同步方法 CopyTo、Read 和 Write。

線程


異步方法旨在成為非阻止操作。異步方法中的 await 表達式在等待的任務正在運行時,不會阻止當前線程。相反,表達式在繼續時,注冊方法的其余部分并將控件返回到異步方法的調用方。

async 和 await 關鍵字不會導致創建其他線程。因為異步方法不會在其自身線程上運行,因此它不需要多線程。 只有當方法處于活動狀態時,該方法將在當前同步上下文中運行并使用線程上的時間。 可以使用 Task.Run 將占用大量 CPU 的工作移到后臺線程,但是后臺線程不會幫助正在等待結果的進程變為可用狀態。

對于異步編程而言,該基于異步的方法優于幾乎每個用例中的現有方法。 具體而言,此方法比 BackgroundWorker 更適用于 IO 綁定的操作,因為此代碼更簡單且無需防止爭用條件。 結合 Task.Run 使用時,異步編程比 BackgroundWorker 更適用于 CPU 綁定的操作,因為異步編程將運行代碼的協調細節與 Task.Run 傳輸至線程池的工作區分開來。

異步和等待


如果通過 async 修飾符指定某種方法為異步方法,則可以啟用以下兩個功能。

  • 標記的異步方法可以使用 await 來指定懸掛點。await 運算符通知編譯器異步方法只有直到等待的異步過程完成才能繼續通過該點。 同時,控件返回至異步方法的調用方。 await 表達式中異步方法的掛起不能使該方法退出,并且 finally 塊不會運行。
  • 標記的異步方法本身可以通過調用它的方法等待。

異步方法通常包含 await 運算符的一個或多個匹配項,但缺少 await 表達式不會導致編譯器錯誤。 如果異步方法未使用 await 運算符標記懸掛點,則該方法將作為同步方法執行,不管異步修飾符如何。編譯器將為此類方法發布一個警告。

Async 、async、Await 和 await 都是上下文關鍵字。 有關更多信息和示例,請參見以下主題:

  • async
  • await

返回類型和參數


.NET Framework 異步編程中異步方法通常返回 Task 或 Task<TResult>。 在異步方法中,await 運算符應用于通過調用另一個異步方法返回的任務。

如果方法包含 Return (Visual Basic) 或指定類型 TResult 的操作數的 return (C#) 語句,則將 Task<TResult> 指定為返回類型。

如果方法不含任何 return 語句或包含不返回操作數的 return 語句,則將 Task 用作返回類型。

下面的示例演示如何聲明并調用可返回 Task<TResult> 或 Task 的方法。

// Signature specifies Task<;TResult>
async Task<;int> TaskOfTResult_MethodAsync()
{
    int hours;
    // . . .
    // Return statement specifies an integer result.
    return hours;
}
 
// Calls to TaskOfTResult_MethodAsync
Task<;int> returnedTaskTResult = TaskOfTResult_MethodAsync();
int intResult = await returnedTaskTResult;
// or, in a single statement
int intResult = await TaskOfTResult_MethodAsync();
// Signature specifies Task
async Task Task_MethodAsync()
{
    // . . .
    // The method has no return statement.  
}
 
// Calls to Task_MethodAsync
Task returnedTask = Task_MethodAsync();
await returnedTask;
// or, in a single statement
await Task_MethodAsync();

每個返回的任務表示正在進行的工作。 任務可封裝有關異步進程狀態的信息,如果未成功,則最后會封裝來自進程的最終結果或進程引發的異常。

異步方法還可以是 Sub 方法 (Visual Basic) 或具有 void 返回類型 (C#)。 該返回類型主要用于定義需要 void 返回類型的事件處理程序。 異步事件處理程序通常用作異步程序的起始點。

無法等待為 Sub 程序或具有 void 返回類型的異步方法,并且無效的返回方法的調用方無法捕獲該方法引發的任何異常。

異步方法無法聲明 Visual Basic 中的 ByRef 參數或 C# 中的 ref 或 out 參數,但此方法可以調用具有此類參數的方法。

有關更多信息和示例,請參見異步返回類型(C# 和 Visual Basic)。 有關如何在異步方法中捕捉異常的更多信息,請參見 try-catch(C# 參考)或 Try...Catch...Finally 語句 (Visual Basic)。

Windows 運行時編程中的異步 API 具有下列返回類型之一,它類似于任務:

  • IAsyncOperation,它對應于 Task<TResult>
  • IAsyncAction,它對應于 Task
  • IAsyncActionWithProgress
  • IAsyncOperationWithProgress

參考資料


  • Microsoft Developer Network 基于任務的異步模式 (TAP)
  • 使用 Async 和 Await 的異步編程
  • 異步程序中的控制流

 

下載 Demo

下載 Demo TPL 與 AMP 和 EAP 結合


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
最近中文字幕2019免费| 亚洲jizzjizz日本少妇| 亚洲欧美日韩精品久久亚洲区| 91av成人在线| 欧美激情乱人伦一区| 亚洲日本欧美日韩高观看| 亚洲色图50p| 久久成人人人人精品欧| 久久久久女教师免费一区| 国产精品嫩草视频| 亚洲第一二三四五区| 一本色道久久88综合日韩精品| 精品无码久久久久久国产| 亚洲欧美国产视频| 97在线看福利| 欧美成人黄色小视频| 中文字幕自拍vr一区二区三区| 欧美精品久久一区二区| 日韩在线视频二区| 国产精品久久久久久av福利软件| 欧美日韩另类在线| 日韩美女主播视频| 国产日韩视频在线观看| 亚洲男人av在线| 亚洲精品v欧美精品v日韩精品| 亚洲图片在线综合| 国产精品偷伦视频免费观看国产| 亚洲精品色婷婷福利天堂| 91精品在线播放| 日韩精品久久久久久久玫瑰园| 亚洲欧洲中文天堂| 最近2019年手机中文字幕| 亚洲国产欧美一区二区三区久久| 8x拔播拔播x8国产精品| 欧美xxxx18性欧美| 久久精品国产欧美亚洲人人爽| 亚洲欧美制服丝袜| 亚洲欧美日韩精品久久亚洲区| 久久的精品视频| 国产精品露脸自拍| 亚洲午夜未满十八勿入免费观看全集| 亚洲欧美成人一区二区在线电影| 国产精品久久国产精品99gif| www国产91| 欧美视频国产精品| 国产精品视频久久久久| 九九热精品视频国产| 成人性生交xxxxx网站| 亚洲精品99久久久久中文字幕| 中文字幕久久久av一区| 国产一区二区三区视频在线观看| 亚洲视频视频在线| 尤物yw午夜国产精品视频明星| 欧美人交a欧美精品| 超薄丝袜一区二区| 欧美肥老太性生活视频| 免费成人高清视频| 福利一区视频在线观看| 日韩av免费在线播放| 在线精品国产成人综合| 欧美黄色三级网站| 日韩女优人人人人射在线视频| 亚洲开心激情网| 久久精品国产欧美亚洲人人爽| 国产精品劲爆视频| 国产精品观看在线亚洲人成网| 欧美日韩一区二区免费视频| 国产精品青青在线观看爽香蕉| 亚洲欧美激情四射在线日| 亚洲人成77777在线观看网| 国产成人精彩在线视频九色| 日韩黄色在线免费观看| 国产成人精品综合久久久| 日韩av在线资源| 日韩欧美第一页| 18性欧美xxxⅹ性满足| 国内外成人免费激情在线视频网站| 亚洲精品一区二区网址| 在线一区二区日韩| 欧美精品一区在线播放| 亚洲视频第一页| 91中文字幕一区| 日韩精品福利在线| 奇门遁甲1982国语版免费观看高清| 久久精品视频播放| 人人澡人人澡人人看欧美| 日韩大胆人体377p| 成人免费看吃奶视频网站| 亚洲社区在线观看| 亚洲欧美999| 66m—66摸成人免费视频| 日韩精品在线观看视频| 国产精品日韩在线观看| 精品亚洲一区二区三区在线观看| 欧美大片在线看免费观看| 国产亚洲视频在线| 国产精品福利在线观看| 色青青草原桃花久久综合| 动漫精品一区二区| 久久国产视频网站| 欧美综合在线观看| 黄网动漫久久久| 欧美日韩国产二区| 欧美小视频在线| 亚洲肉体裸体xxxx137| 欧美性视频网站| 亚洲人成网站999久久久综合| 欧美成人免费观看| 91免费在线视频| 精品视频—区二区三区免费| 国产剧情日韩欧美| 午夜欧美大片免费观看| 91久久精品美女| 色婷婷综合成人av| 欧美激情综合色综合啪啪五月| 欧美精品电影在线| 日韩av片免费在线观看| 在线视频一区二区| 日韩电影免费观看在线观看| 久久视频国产精品免费视频在线| 日韩美女在线看| 韩国国内大量揄拍精品视频| 伊人伊成久久人综合网站| 成人激情视频免费在线| 国产精品va在线| 亚洲色图在线观看| 91欧美精品午夜性色福利在线| 成人h片在线播放免费网站| 精品爽片免费看久久| 热99精品只有里视频精品| 成人观看高清在线观看免费| 亚洲国产精品国自产拍av秋霞| 久久久久久亚洲精品不卡| 日韩免费精品视频| 久久视频在线免费观看| 国产成人精品久久| 欧美一级片在线播放| 久久久99免费视频| 日日摸夜夜添一区| 97视频在线观看成人| 久久久久久久久久久人体| 亚洲美女动态图120秒| 国模私拍一区二区三区| 亚洲女成人图区| 国产成人啪精品视频免费网| 久久精品国产一区二区三区| 欧美精品成人91久久久久久久| 中文字幕一区二区三区电影| 国产欧美在线观看| 日韩av理论片| 久久免费精品日本久久中文字幕| 欧美精品午夜视频| 国产精品久久久久久久久粉嫩av| 97精品一区二区视频在线观看| 国产欧美精品一区二区三区-老狼| 91老司机精品视频| 精品一区精品二区| 日本精品久久久| 国产在线视频欧美| 日韩精品视频中文在线观看| 欧美高清videos高潮hd| 久久成人在线视频| 91久久久久久久一区二区| 亚洲欧美在线免费观看|