[.NET] 利用 async & await 進行非同步 IO 操作(整理中...)

来源:http://www.cnblogs.com/liqingwen/archive/2016/11/20/6082673.html
-Advertisement-
Play Games

利用 async & await 進行非同步 IO 操作 可以使用非同步函數訪問文件。使用非同步功能,可以調用非同步方法,而不使用回調或拆分您在多個方法或 lambda 表達式中的代碼。 若要使同步代碼非同步,則調用非同步方法而不是一個同步方法並添加幾個關鍵字到代碼中。 對文件操作使用非同步特性: 非同步特性有利於 ...


利用 async & await 進行非同步 IO 操作

  可以使用非同步函數訪問文件。使用非同步功能,可以調用非同步方法,而不使用回調或拆分您在多個方法或 lambda 表達式中的代碼。 若要使同步代碼非同步,則調用非同步方法而不是一個同步方法並添加幾個關鍵字到代碼中。

  對文件操作使用非同步特性:

  • 非同步特性有利於應用程式的響應能力更強。因為一個操作的 UI 線程可以執行其他工作。 如果 UI 線程必須執行需要很長時間的代碼(例如,超過 50 毫秒),UI 可以凍結,直到 I/O 完成的,並且用戶界麵線程可以重新處理鍵盤和滑鼠輸入和其他操作。

  • 非同步特性有利於通過減少對線程的需要增強 ASP.NET 和其他的可伸縮性基於伺服器的應用程式。 如果應用程式使用專用線程上每個響應,並且一次兩個請求同時處理,則有線程是必需的。 在等待期間,非同步操作通常不需要使用線程。 它們簡要使用現有的 I/O 完成線程在末尾。

  • 文件訪問操作的延遲在本地也許非常低,但是,我們可以考慮一下文件在非本地時進行的操作。 例如,文件可能會存放位於遠程的伺服器。

  • 使用非同步額外增加的開銷很小。

  • 非同步任務可以並行運行。

 

使用 FileStream 

  示例使用 FileStream 類,它具有一個選項導致非同步 I/O 發生在操作系統級別。使用此選項,您可以避免在許多情況下阻止線程池線程。 若要啟用此選項,則指定 useAsync=true 或在構造函數中 options=FileOptions.Asynchronous 參數調用。

  不能對 StreamReader 和 StreamWriter 的此選項,如果直接通過指定文件路徑打開這些文件。 但是,您可以使用此選項,則提供自己 FileStream 類打開的 Stream。 請註意,非同步調用是比在 UI app,即使線程池線程阻塞,在等待期間,因為用戶界麵線程未阻止。

 

編寫文本

  下麵的示例寫入文本到文件。 在每個請等待語句,則此方法會立即退出。 當文件 I/O 完成時,方法以等待語句後面的語句。 請註意"修飾符在使用等待語句方法的定義。

1         private async void btnWrite_Click(object sender, RoutedEventArgs e)
2         {
3             await WriteTextAsync();
4         }
btnWrite_Click

 

 1         /// <summary>
 2         /// 非同步寫入文件
 3         /// </summary>
 4         /// <returns></returns>
 5         private async Task WriteTextAsync()
 6         {
 7             var path = $"temp.txt";
 8             var content = Guid.NewGuid().ToString();
 9 
10             using (var fs = new FileStream(path,
11                 FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None, bufferSize: 4096, useAsync: true))
12             {
13                 var buffer = Encoding.UTF8.GetBytes(content);
14 
15                 //var writeTask = fs.WriteAsync(buffer, 0, buffer.Length);
16                 //await writeTask;
17                 await fs.WriteAsync(buffer, 0, buffer.Length);
18             }
19         }

  行號 17 的語句可以修改為:

1   //await fs.WriteAsync(buffer, 0, buffer.Length);
2   //可以改為
3   var writeTask = fs.WriteAsync(buffer, 0, buffer.Length);
4   await writeTask;

  第一個語句(行號 1)返回任務並導致進程的文件。 使用等待的第二個語句(行號3、4)導致方法立即退出並返回其他任務。 當隨後處理的文件完成時,執行回 await 的語句。 

 

讀取文本

  下麵的示例從文件中讀取文本。 該文本緩衝區,因此,在這種情況下,將被放入 StringBuilder。 不同於在前面的示例中,等待的計算生成值。ReadAsync 方法返回 Task<Int32>,因此,等待的計算生成一個 Int32 值(numRead),在操作完成之後。

 1         /// <summary>
 2         /// 非同步讀取文本
 3         /// </summary>
 4         /// <param name="fileName"></param>
 5         /// <returns></returns>
 6         private async Task<string> ReadTextAsync(string fileName)
 7         {
 8             using (var fs = new FileStream(fileName,
 9                 FileMode.OpenOrCreate, FileAccess.Read, FileShare.None, bufferSize: 4096, useAsync: true))
10             {
11                 var sb = new StringBuilder();
12                 var buffer = new byte[0x1000];  //十六進位 等於十進位的 4096
13                 var readLength = 0;
14 
15                 while ((readLength = await fs.ReadAsync(buffer, 0, buffer.Length)) != 0)
16                 {
17                     var text = Encoding.UTF8.GetString(buffer, 0, readLength);
18                     sb.Append(text);
19                 }
20 
21                 return sb.ToString();
22             }
23         }

 

 1         private async void btnRead_Click(object sender, RoutedEventArgs e)
 2         {
 3             var fileName = $"temp.txt";
 4             if (!File.Exists(fileName))
 5             {
 6                 Debug.WriteLine($"文件找不到:{fileName}");
 7                 return;
 8             }
 9 
10             try
11             {
12                 var content = await ReadTextAsync(fileName);
13                 Debug.WriteLine(content);
14             }
15             catch (Exception ex)
16             {
17                 Debug.WriteLine(ex.Message);
18             }
19         }
btnRead_Click

 

並行非同步 I/O

  下麵的示例通過編寫 10 個文本文件演示並行處理。 對於每個文件,WriteAsync 方法返回然後添加到任務列表的任務。文件時,在處理為所有完成的任務時,await Task.WhenAll(tasks); 語句退出方法併在方法中恢復。

  在任務完成後,該示例以 finally 的所有 FileStream 實例塊。 如果每 FileStream 在 using 語句中創建的,FileStream 可能已處理,在任務完成之前。

  【註意】所有性能提高幾乎完全是從非同步處理的並行處理。 非同步的優點是它不會占用多個線程,因此,它不會占用用戶界麵線程。

 1         /// <summary>
 2         /// 非同步寫入多個文件
 3         /// </summary>
 4         /// <param name="folder"></param>
 5         /// <returns></returns>
 6         private async Task WriteMultiTextAsync(string folder)
 7         {
 8             var tasks = new List<Task>();
 9             var fileStreams = new List<FileStream>();
10 
11             try
12             {
13                 for (int i = 1; i <= 10; i++)
14                 {
15                     var fileName = Path.Combine(folder, $"{i}.txt");
16                     var content = Guid.NewGuid().ToString();
17                     var buffer = Encoding.UTF8.GetBytes(content);
18 
19                     var fs = new FileStream(fileName,
20         FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None, bufferSize: 4096, useAsync: true);
21                     fileStreams.Add(fs);
22 
23                     var writeTask = fs.WriteAsync(buffer, 0, buffer.Length);
24                     tasks.Add(writeTask);
25                 }
26 
27                 await Task.WhenAll(tasks);
28             }
29             finally
30             {
31                 foreach (var fs in fileStreams)
32                 {
33                     fs.Close();
34                     fs.Dispose();
35                 }
36             }
37         }

 

 1         private async void btnWriteMulti_Click(object sender, RoutedEventArgs e)
 2         {
 3             var folder = $"temp";
 4 
 5             if (!Directory.Exists(folder))
 6             {
 7                 Directory.CreateDirectory(folder);
 8             }
 9 
10             await WriteMultiTextAsync(folder);
11         }
btnWriteMulti_Click

  在使用 WriteAsync 和 ReadAsync 方案時,可以指定 CancellationToken,來在中途取消操作。 

 

 


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

-Advertisement-
Play Games
更多相關文章
  • 當我們在linux上, 使用yum 安裝包時,報錯如下: 這時我們需要安裝EPEL EPEL,即Extra Packages for Enterprise Linux,這個軟體倉庫里有很多非常常用的軟體,而且是專門針對RHEL設計的,對RHEL標準yum源是一個很好的補充,完全免費使用,由Fedor ...
  • 問題 如何控制 OData 路由 解決方案 為了註冊路由,可以使用 HttpConfigurationExtension 類中 MapODataServiceRoute 的擴展方法。對於單一路由這樣做足以,其餘的處理由實體數據模型來處理。 從 ASP.NET Web API 2.2 開始支持 ODa ...
  • 我們看看各個web框架的性能,以TPS為指標排序(每秒返回的response多的在前面,性能越好),所有測試都在Linux中運行。在對比中,我們看到ASP.NET Core取得優異的成績,具體6個回合的對比請移步TechEmpower查看 ...
  • 怎樣使用 async & await 一步步將同步代碼轉換為非同步編程 【博主】反骨仔 【出處】http://www.cnblogs.com/liqingwen/p/6079707.html 序 上次,博主通過《利用 async & await 的非同步編程》一文介紹了 async & await 的基 ...
  • 在工業領域也有極端的情況出現,早些年做通訊的時候,數據包頭、包尾、數據長度、數據校驗位都對,但是就是解析出來的數據不正確,這種情況不會經常出現,但是在某種特殊應用環境可能會頻繁出現,後來經過分析得出結論:可能是由於地質電磁干擾引起的。但是也有技術上的設計缺陷,例如:數據校驗位是累加和,改成CRC是不... ...
  • Visual Studio for Mac離線下載安裝。 環境:OS X EI Caption 10.11.2 .NET Core SDK 1.1 需預先安裝 .NET Core 1.1 SDK macOS版下載地址:https://go.microsoft.com/fwlink/?LinkID=8 ...
  • 前面幾篇重點都在講普通列表的相關操作,本篇主要講樹型列表的操作,詳情如下:... ...
  • 1、字母大小寫處理 2、字母與ASCII的互換 在Web開發時,ASCII的作用!(American Standard Code for Information Interchange,美國信息交換標準代碼) 舉個例子:' 單引號在sql語句中是個殺手,但是如果把(')它轉換成 "&#" + ASC ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...