비동기 작업을 사용하면 주 스레드를 차단하지 않고 리소스 집약적 I/O 작업을 수행할 수 있습니다. 이 성능 고려 사항은 시간이 많이 걸리는 스트림 작업이 UI 스레드를 차단하고 앱이 작동하지 않는 것처럼 표시되도록 할 수 있는 Windows 8.x 스토어 앱 또는 데스크톱 앱에서 특히 중요합니다.
.NET Framework 4.5부터 I/O 형식에는 비동기 작업을 간소화하는 비동기 메서드가 포함됩니다. 비동기 메서드는 Async
이름(예: ReadAsync, WriteAsync, CopyToAsyncFlushAsync, ReadLineAsync및 ReadToEndAsync)을 포함합니다. 이러한 비동기 메서드는 스트림 클래스인 Stream, FileStream, MemoryStream 및 스트림에서 읽거나 스트림에 쓰는 데 사용되는 클래스인 TextReader, TextWriter에 구현됩니다.
.NET Framework 4 및 이전 버전에서는 비동기 I/O 작업과 BeginRead 같은 EndRead 메서드를 사용하고 구현해야 합니다. 이러한 메서드는 레거시 코드를 지원하기 위해 현재 .NET 버전에서 계속 사용할 수 있습니다. 그러나 비동기 메서드를 사용하면 비동기 I/O 작업을 보다 쉽게 구현할 수 있습니다.
C# 및 Visual Basic에는 각각 비동기 프로그래밍을 위한 두 개의 키워드가 있습니다.
Async
(Visual Basic) 또는async
(C#) 한정자는 비동기 작업이 포함된 메서드를 표시하는 데 사용됩니다.Await
비동기 메서드의 결과에 적용되는 (Visual Basic) 또는await
(C#) 연산자입니다.
비동기 I/O 작업을 구현하려면 다음 예제와 같이 비동기 메서드와 함께 이러한 키워드를 사용합니다. 자세한 내용은 비동기 및 await를 사용한 비동기 프로그래밍(C#) 또는 Async 및 Await를 사용한 비동기 프로그래밍(Visual Basic)을 참조하세요.
다음 예제에서는 두 FileStream 개체를 사용하여 한 디렉터리에서 다른 디렉터리로 파일을 비동기적으로 복사하는 방법을 보여 줍니다.
Click 이벤트 처리기는 Button 컨트롤의 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(Path.Combine(endDirectory, Path.GetFileName(filename))))
{
await sourceStream.CopyToAsync(destinationStream);
}
}
}
}
}
}
Imports System.IO
Class MainWindow
Private Async Sub Button_Click(sender As Object, e As RoutedEventArgs)
Dim StartDirectory As String = "c:\Users\exampleuser\start"
Dim EndDirectory As String = "c:\Users\exampleuser\end"
For Each filename As String In Directory.EnumerateFiles(StartDirectory)
Using SourceStream As FileStream = File.Open(filename, FileMode.Open)
Using DestinationStream As FileStream = File.Create(EndDirectory + filename.Substring(filename.LastIndexOf("\"c)))
Await SourceStream.CopyToAsync(DestinationStream)
End Using
End Using
Next
End Sub
End Class
다음 예제는 이전 예제와 비슷하지만 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);
}
}
Private Async Sub Button_Click(sender As Object, e As RoutedEventArgs)
Dim UserDirectory As String = "c:\Users\exampleuser\"
Using SourceReader As StreamReader = File.OpenText(UserDirectory + "BigFile.txt")
Using DestinationWriter As StreamWriter = File.CreateText(UserDirectory + "CopiedFile.txt")
Await CopyFilesAsync(SourceReader, DestinationWriter)
End Using
End Using
End Sub
Public Async Function CopyFilesAsync(Source As StreamReader, Destination As StreamWriter) As Task
Dim buffer(4095) As Char
Dim numRead As Integer
numRead = Await Source.ReadAsync(buffer, 0, buffer.Length)
Do While numRead <> 0
Await Destination.WriteAsync(buffer, 0, numRead)
numRead = Await Source.ReadAsync(buffer, 0, buffer.Length)
Loop
End Function
다음 예제에서는 Windows 8.x 스토어 앱에서 Stream로 파일을 열고 StreamReader 클래스의 인스턴스를 사용하여 콘텐츠를 읽는 데 사용되는 코드 숨김 파일과 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
{
public sealed partial class BlankPage : Page
{
public BlankPage()
{
this.InitializeComponent();
}
private async void 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();
}
}
}
Imports System.Text
Imports System.IO
Imports Windows.Storage.Pickers
Imports Windows.Storage
NotInheritable Public Class BlankPage
Inherits Page
Private Async Sub Button_Click_1(sender As Object, e As RoutedEventArgs)
Dim contents As StringBuilder = New StringBuilder()
Dim nextLine As String
Dim lineCounter As Integer = 1
Dim openPicker = New FileOpenPicker()
openPicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary
openPicker.FileTypeFilter.Add(".txt")
Dim selectedFile As StorageFile = Await openPicker.PickSingleFileAsync()
Using reader As StreamReader = New StreamReader(Await selectedFile.OpenStreamForReadAsync())
nextLine = Await reader.ReadLineAsync()
While (nextLine <> Nothing)
contents.AppendFormat("{0}. ", lineCounter)
contents.Append(nextLine)
contents.AppendLine()
lineCounter = lineCounter + 1
If (lineCounter > 3) Then
contents.AppendLine("Only first 3 lines shown.")
Exit While
End If
nextLine = Await reader.ReadLineAsync()
End While
End Using
DisplayContentsBlock.Text = contents.ToString()
End Sub
End Class
<Page
x:Class="ExampleApplication.BlankPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ExampleApplication"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<StackPanel Background="{StaticResource ApplicationPageBackgroundBrush}" VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock Text="Display lines from a file."></TextBlock>
<Button Content="Load File" Click="Button_Click_1"></Button>
<TextBlock Name="DisplayContentsBlock"></TextBlock>
</StackPanel>
</Page>
참고하십시오
.NET