非同期ファイル I/OAsynchronous File I/O

非同期操作では、メイン スレッドをブロックすることなくリソース使用量の多い I/O 操作を実行できます。Asynchronous operations enable you to perform resource-intensive I/O operations without blocking the main thread. このパフォーマンスに関する考慮事項は、時間のかかるストリーム操作によって UI スレッドがブロックされ、アプリが動作していないと見なされる可能性がある Windows 8.x ストアWindows 8.x Store アプリまたはデスクトップ アプリで特に重要です。This performance consideration is particularly important in a Windows 8.x ストアWindows 8.x Store app or desktop app where a time-consuming stream operation can block the UI thread and make your app appear as if it is not working.

.NET Framework 4.5 以降の I/O 型には非同期操作を単純化する非同期メソッドが含まれています。Starting with the .NET Framework 4.5, the I/O types include async methods to simplify asynchronous operations. 非同期のメソッドの名前には Async が含まれます ( ReadAsyncWriteAsyncCopyToAsyncFlushAsyncReadLineAsyncReadToEndAsyncなど)。An async method contains Async in its name, such as ReadAsync, WriteAsync, CopyToAsync, FlushAsync, ReadLineAsync, and ReadToEndAsync. これらの非同期のメソッドは、 StreamFileStreamMemoryStreamなどのストリーム クラスと、 TextReaderTextWriterなどのストリームとの間の読み取り/書き込みに使用されるクラスに実装されます。These async methods are implemented on stream classes, such as Stream, FileStream, and MemoryStream, and on classes that are used for reading from or writing to streams, such TextReader and TextWriter.

.NET Framework 4 およびそれ以前のバージョンで非同期 I/O 操作を実装するには、 BeginReadEndRead などのメソッドを使用する必要があります。In the .NET Framework 4 and earlier versions, you have to use methods such as BeginRead and EndRead to implement asynchronous I/O operations. これらのメソッドは、レガシ コードをサポートするために .NET Framework 4.5 でも使用できますが、非同期 I/O 操作は非同期のメソッドを使用して実装する方が簡単です。These methods are still available in the .NET Framework 4.5 to support legacy code; however, the async methods help you implement asynchronous I/O operations more easily.

C# と Visual Basic には、非同期プログラミング用のキーワードがそれぞれ 2 つあります。C# and Visual Basic each have two keywords for asynchronous programming:

  • Async (Visual Basic) 修飾子または async (C#) 修飾子。非同期操作を含むメソッドをマークするために使用されます。Async (Visual Basic) or async (C#) modifier, which is used to mark a method that contains an asynchronous operation.

  • Await (Visual Basic) 演算子または await (C#) 演算子。非同期のメソッドの結果に適用されます。Await (Visual Basic) or await (C#) operator, which is applied to the result of an async method.

非同期 I/O 操作を実装するには、これらのキーワードを非同期のメソッドと組み合わせて使用します。次に例を示します。To implement asynchronous I/O operations, use these keywords in conjunction with the async methods, as shown in the following examples. 詳細については、「Async および Await を使用した非同期プログラミング (C#)」または「Async および Await を使用した非同期プログラミング (Visual Basic)」を参照してください。For more information, see Asynchronous programming with async and await (C#) or Asynchronous Programming with Async and Await (Visual Basic).

次の例では、2 つの FileStream オブジェクトを使用して、ファイルをディレクトリ間で非同期にコピーする方法を示します。The following example demonstrates how to use two FileStream objects to copy files asynchronously from one directory to another. 非同期のメソッドを呼び出すので、 Click コントロールの Button イベント ハンドラーは async 修飾子でマークされていることに注意してください。Notice that the Click event handler for the Button control is marked with the async modifier because it calls an asynchronous method.

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);
                    }
                }
            }
        }
    }
}
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 オブジェクトを使用して、テキスト ファイルの内容の読み取り/書き込みを非同期で行います。The next example is similar to the previous one but uses StreamReader and StreamWriter objects to read and write the contents of a text file asynchronously.

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(4096) 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

次の例では、分離コード ファイルと XAML ファイルを使用して Stream アプリでファイルを Windows 8.x ストアWindows 8.x Store として開き、 StreamReader クラスのインスタンスを使用してその内容を読み取る方法を示します。The next example shows the code-behind file and the XAML file that are used to open a file as a Stream in a Windows 8.x ストアWindows 8.x Store app, and read its contents by using an instance of the StreamReader class. ここでは、非同期のメソッドを使用して、ファイルをストリームとして開き、ファイルの内容を読み取ります。It uses asynchronous methods to open the file as a stream and to read its contents.

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>

関連項目See also