非同步作業可以執行大量佔用資源的 I/O 操作,而不必阻止主線程。 此效能注意事項非常重要。 windows Metro style app 或 desktop app 耗時的流操作會阻止 UI 線程並將您的應用程式顯示的位置,就象它不起作用。
從開始 .NET Framework 4.5 RC, I/O 類型包括非同步方法呼叫簡化非同步作業。 非同步方法呼叫在其名稱中包含 Async ,例如 ReadAsync、 WriteAsync、 CopyToAsync、 FlushAsync、 ReadLineAsync和 ReadToEndAsync。 這些非同步方法呼叫對流類,如 Stream、 FileStream和 MemoryStream以及用於讀取或寫入使用至流 (如 TextReader 和 TextWriter的類。
在 .NET framework 4 和早期版本中,必須使用之類的方法 BeginRead 和 EndRead 實現非同步 I/O 操作。 這些方法可在 .NET Framework 4.5 RC 支援舊版代碼;但是,非同步方法呼叫協助您更輕鬆地實現非同步 I/O 操作。
從開始 Visual Studio 2012 RC, Visual Studio 為非同步編程提供兩個關鍵字:
如下面的樣本所示,若要實現非同步 I/O 操作,請使用非同步方法呼叫結合使用這些關鍵字,。 有關更多資訊,請參見 非同步編程與非同步和等待 (C# 和 Visual Basic)。
下面的樣本示範如何使用複製檔案的兩 FileStream 對象非同步從一個目錄到另一個。 請注意 Button 控制項的 Click 事件處理常式標記 async 修飾符,因為它調用非同步方法呼叫。
using System;using System.Threading.Tasks;using System.Windows;using System.IO;namespace WpfApplication{ public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private async void Button_Click(object sender, RoutedEventArgs e) { string StartDirectory = @"c:\Users\exampleuser\start"; string EndDirectory = @"c:\Users\exampleuser\end"; foreach (string filename in Directory.EnumerateFiles(StartDirectory)) { using (FileStream SourceStream = File.Open(filename, FileMode.Open)) { using (FileStream DestinationStream = File.Create(EndDirectory + filename.Substring(filename.LastIndexOf('\\')))) { await SourceStream.CopyToAsync(DestinationStream); } } } } }}
下一個樣本與前一個樣本相似,但使用 StreamReader 和 StreamWriter 對象讀取和寫入文字檔的內容非同步。
private async void Button_Click(object sender, RoutedEventArgs e){ string UserDirectory = @"c:\Users\exampleuser\"; using (StreamReader SourceReader = File.OpenText(UserDirectory + "BigFile.txt")) { using (StreamWriter DestinationWriter = File.CreateText(UserDirectory + "CopiedFile.txt")) { await CopyFilesAsync(SourceReader, DestinationWriter); } }}public async Task CopyFilesAsync(StreamReader Source, StreamWriter Destination) { char[] buffer = new char[0x1000]; int numRead; while ((numRead = await Source.ReadAsync(buffer, 0, buffer.Length)) != 0) { await Destination.WriteAsync(buffer, 0, numRead); } }
使用 StreamReader 類的執行個體,下一個樣本示範用於開啟檔案為 Metro style app 的 Stream 的程式碼後置檔案和 XAML 檔案之後和讀取其內容。 它使用非同步方法呼叫開啟檔案以流和讀取其內容。
using System;using System.IO;using System.Text;using Windows.Storage.Pickers;using Windows.Storage;using Windows.UI.Xaml;using Windows.UI.Xaml.Controls;namespace ExampleApplication{ publicsealedpartialclass BlankPage : Page { public BlankPage() { this.InitializeComponent(); } privateasyncvoid Button_Click_1(object sender, RoutedEventArgs e) { StringBuilder contents = new StringBuilder(); string nextLine; int lineCounter = 1; var openPicker = new FileOpenPicker(); openPicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary; openPicker.FileTypeFilter.Add(".txt"); StorageFile selectedFile = await openPicker.PickSingleFileAsync(); using (StreamReader reader = new StreamReader(await selectedFile.OpenStreamForReadAsync())) { while ((nextLine = await reader.ReadLineAsync()) != null) { contents.AppendFormat("{0}. ", lineCounter); contents.Append(nextLine); contents.AppendLine(); lineCounter++; if (lineCounter > 3) { contents.AppendLine("Only first 3 lines shown."); break; } } } DisplayContentsBlock.Text = contents.ToString(); } }}