Verwenden von Async für Dateizugriff (C# und Visual Basic)

Sie können die Async-Funktion verwenden, um auf Dateien zugreifen. Indem Sie die asynchrone Funktion verwenden, können Sie in asynchronen Methoden aufrufen, ohne Rückrufe zu verwenden oder den Code über mehrere Methoden oder Lambda-Ausdrücken zu teilen. Um synchronen Codes asynchron auszuführen, rufen Sie nur eine asynchrone Methode anstelle einer synchronen Methode auf und einige Schlüsselwörter dem Code hinzu.

Sie könnten die folgenden Gründe zum Hinzufügen als asynchrony zu den Dateizugriffsaufrufen:

  • Asynchrony stellt Benutzeroberfläche-Anträge schneller, da der UI-Thread, das der Vorgang startet, andere Aufgaben ausführen kann. Wenn der UI-Thread Code ausführen muss, der eine lange Verarbeitungszeit (beispielsweise, mehr als 50 Millisekunden) erwartet, sperrt möglicherweise die Benutzeroberfläche ein, bis die E/A abgeschlossen wurde und der UI-Thread Tastatur- und Mauseingaben und andere Ereignisse erneut verarbeiten kann.

  • Asynchrony verbessert die Skalierbarkeit von ASP.NET und anderen serverbasierten Anwendungen, indem er die Anforderung für Threads reduziert. Wenn die Anwendung einen dedizierten Thread pro Antwort verwendet und tausend Anforderungen gleichzeitig bearbeitet werden, werden tausend Threads erforderlich. Asynchrone Vorgänge häufig, müssen keinen Thread während des Wartevorgangs zu verwenden. Sie verwenden den vorhandenen E/A-Komplettierungs-Thread kurz am Ende.

  • Die Wartezeit eines Dateizugriffsvorgangs kann sehr niedrige untere aktuelle Bedingungen, die Wartezeit erhöht sich groß möglicherweise in der Zukunft. Beispielsweise wird eine Datei auf einem Server verschoben werden, der über der Welt ist.

  • Der hinzugefügte Mehraufwand der Anwendung der Async-Funktion ist klein.

  • Asynchrone Aufgaben können problemlos parallel ausgeführt werden.

Ausführen der Beispiele

Hinweis

Die Beispiele in diesem Thema gelten nicht für Windows Store Apps, die Windows 8 App sind, die Ganzseiten- und für Fingereingabeinteraktion angepasst sind.Informationen darüber, wie asynchrone Dateizugriff in Windows Store App, finden Sie unter .NET für Windows Store-Apps – Übersicht und Datei- und Stream-E/A verwendet.Beispiele für Datei-E/A für Windows Store App, können Sie herunterladen Dateizugriffs-Beispiel.

Um die Beispiele in diesem Thema auszuführen, können Sie WPF-Anwendung oder Windows Forms-Anwendung erstellen und Schaltfläche hinzufügen. Click im - Ereignis der Schaltfläche fügen Sie einen Aufruf der ersten Methode in jedem Beispiel hinzu.

In den folgenden Beispielen schließen Sie folgende Imports (Visual Basic) oder - Anweisungen using (C#) ein.

Imports System
Imports System.Collections.Generic
Imports System.Diagnostics
Imports System.IO
Imports System.Text
Imports System.Threading.Tasks
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading.Tasks;

Verwendung der Dateidatenstrom-Klasse

Die Beispiele in diesem Thema werden die FileStream-Klasse, die eine Option hat, die asynchrone E/A bewirkt, dass auf der Betriebssystemebene fungiert. Mit dieser Option verwenden, können Sie einen, Threadpoolthread in vielen Fällen zu blockieren vermeiden. Um diese Option zu aktivieren, geben Sie das useAsync=true oder options=FileOptions.Asynchronous-Argument im Konstruktoraufruf an.

Sie können diese Option mit StreamReader und StreamWriter nicht verwenden, wenn Sie sie direkt öffnen, indem Sie einen Dateipfad angeben. Sie können diese Option verwenden, wenn Sie ihnen Stream bereitstellen, das die FileStream-Klasse geöffnet hat. Beachten Sie, dass asynchrone Aufrufe in Benutzeroberfläche-Apps schneller sind, selbst wenn ein Threadpoolthread blockiert wird, da der UI-Thread nicht während des Wartevorgangs blockiert wird.

Schreiben von Text

Im folgenden Beispiel schreibt Text in eine Datei. Zu jedem erwarten Sie Anweisung, wird die Methode sofort. Wenn die Datei-E/A abgeschlossen ist, die Methodenzusammenfassungen mit der Anweisung, die der Erwartungsanweisung folgt. Beachten Sie, dass der asynchrone Modifizierer in der Definition von Methoden ist, die die Erwartungsanweisung verwenden.

Public Async Sub ProcessWrite()
    Dim filePath = "temp2.txt" 
    Dim text = "Hello World" & ControlChars.CrLf

    Await WriteTextAsync(filePath, text)
End Sub 

Private Async Function WriteTextAsync(filePath As String, text As String) As Task
    Dim encodedText As Byte() = Encoding.Unicode.GetBytes(text)

    Using sourceStream As New FileStream(filePath,
        FileMode.Append, FileAccess.Write, FileShare.None,
        bufferSize:=4096, useAsync:=True)

        Await sourceStream.WriteAsync(encodedText, 0, encodedText.Length)
    End Using 
End Function
public async void ProcessWrite()
{
    string filePath = @"temp2.txt";
    string text = "Hello World\r\n";

    await WriteTextAsync(filePath, text);
}

private async Task WriteTextAsync(string filePath, string text)
{
    byte[] encodedText = Encoding.Unicode.GetBytes(text);

    using (FileStream sourceStream = new FileStream(filePath,
        FileMode.Append, FileAccess.Write, FileShare.None,
        bufferSize: 4096, useAsync: true))
    {
        await sourceStream.WriteAsync(encodedText, 0, encodedText.Length);
    };
}

Das ursprüngliche Beispiel verfügt die - Anweisung await sourceStream.WriteAsync(encodedText, 0, encodedText.Length);, die eine Kontraktion der beiden folgenden Anweisungen ist:

Dim theTask As Task = sourceStream.WriteAsync(encodedText, 0, encodedText.Length)
Await theTask
Task theTask = sourceStream.WriteAsync(encodedText, 0, encodedText.Length);
await theTask;

Die erste - Anweisung gibt eine Aufgabe zurück und verursacht Datei zu starten, die Verarbeitung. Die zweite - Anweisung mit dem Erwartung bewirkt, dass die - Methode eine andere Aufgabe sofort zu beenden und zurückzugeben. Wenn die Datei, die später verarbeitet, abgeschlossen hat, gibt die Ausführung mit der - Anweisung zurück, die dem Erwartung folgt. Weitere Informationen finden Sie unter Ablaufsteuerung in asynchronen Programmen (C# und Visual Basic) und Exemplarische Vorgehensweise: Verwenden des Debuggers mit Async-Methoden.

Lesen von Text

Im folgenden Beispiel wird Text aus einer Datei gelesen. Der Text wird und gepuffert platziert in diesem Fall in StringBuilder. Im Gegensatz zu im vorherigen Beispiel erzeugt die Auswertung des erwartet einen Wert. Die - Methode gibt ReadAsyncTask<Int32> zurück, damit erzeugt die Auswertung des erwartet einen Int32-Wert (numRead) nach Abschluss der Operation. Weitere Informationen finden Sie unter Asynchrone Rückgabetypen (C# und Visual Basic).

Public Async Sub ProcessRead()
    Dim filePath = "temp2.txt" 

    If File.Exists(filePath) = False Then
        Debug.WriteLine("file not found: " & filePath)
    Else 
        Try 
            Dim text As String = Await ReadTextAsync(filePath)
            Debug.WriteLine(text)
        Catch ex As Exception
            Debug.WriteLine(ex.Message)
        End Try 
    End If 
End Sub 

Private Async Function ReadTextAsync(filePath As String) As Task(Of String)

    Using sourceStream As New FileStream(filePath,
        FileMode.Open, FileAccess.Read, FileShare.Read,
        bufferSize:=4096, useAsync:=True)

        Dim sb As New StringBuilder

        Dim buffer As Byte() = New Byte(&H1000) {}
        Dim numRead As Integer
        numRead = Await sourceStream.ReadAsync(buffer, 0, buffer.Length)
        While numRead <> 0
            Dim text As String = Encoding.Unicode.GetString(buffer, 0, numRead)
            sb.Append(text)

            numRead = Await sourceStream.ReadAsync(buffer, 0, buffer.Length)
        End While 

        Return sb.ToString
    End Using 
End Function
public async void ProcessRead()
{
    string filePath = @"temp2.txt";

    if (File.Exists(filePath) == false)
    {
        Debug.WriteLine("file not found: " + filePath);
    }
    else
    {
        try
        {
            string text = await ReadTextAsync(filePath);
            Debug.WriteLine(text);
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
        }
    }
}

private async Task<string> ReadTextAsync(string filePath)
{
    using (FileStream sourceStream = new FileStream(filePath,
        FileMode.Open, FileAccess.Read, FileShare.Read,
        bufferSize: 4096, useAsync: true))
    {
        StringBuilder sb = new StringBuilder();

        byte[] buffer = new byte[0x1000];
        int numRead;
        while ((numRead = await sourceStream.ReadAsync(buffer, 0, buffer.Length)) != 0)
        {
            string text = Encoding.Unicode.GetString(buffer, 0, numRead);
            sb.Append(text);
        }

        return sb.ToString();
    }
}

Parallele asynchrone E/A

Im folgenden Beispiel wird die parallele Verarbeitung, indem 10 Textdateien. Für jede Datei gibt die WriteAsync-Methode eine Aufgabe zurück, die dann an eine Liste von Aufgaben hinzugefügt wird. Die await Task.WhenAll(tasks);-Anweisung beendet die - Methode und die Zusammenfassungen in der Methode, wenn das Dateiverarbeiten für alle Aufgaben abgeschlossen ist.

Das Beispiel umfasst alle FileStream-Instanzen in einem finally-Block, nachdem die Aufgaben abgeschlossen sind. Wenn jedes FileStream stattdessen in einer using-Anweisung erstellt wurde, wird FileStream verworfen werden, bevor die Aufgabe abgeschlossen war.

Beachten Sie, dass jeder Leistungssteigerung nahezu vollständig aus der Verarbeitung und nicht von der asynchronen Verarbeitung ist. Die Vorteile von asynchrony wissen, dass er nicht in mehrere Threads gebunden ist und dass er nicht nach dem Benutzeroberflächenthread bindet.

Public Async Sub ProcessWriteMult()
    Dim folder = "tempfolder\" 
    Dim tasks As New List(Of Task)
    Dim sourceStreams As New List(Of FileStream)

    Try 
        For index = 1 To 10
            Dim text = "In file " & index.ToString & ControlChars.CrLf

            Dim fileName = "thefile" & index.ToString("00") & ".txt" 
            Dim filePath = folder & fileName

            Dim encodedText As Byte() = Encoding.Unicode.GetBytes(text)

            Dim sourceStream As New FileStream(filePath,
                FileMode.Append, FileAccess.Write, FileShare.None,
                bufferSize:=4096, useAsync:=True)

            Dim theTask As Task = sourceStream.WriteAsync(encodedText, 0, encodedText.Length)
            sourceStreams.Add(sourceStream)

            tasks.Add(theTask)
        Next

        Await Task.WhenAll(tasks)
    Finally 
        For Each sourceStream As FileStream In sourceStreams
            sourceStream.Close()
        Next 
    End Try 
End Sub
public async void ProcessWriteMult()
{
    string folder = @"tempfolder\";
    List<Task> tasks = new List<Task>();
    List<FileStream> sourceStreams = new List<FileStream>();

    try
    {
        for (int index = 1; index <= 10; index++)
        {
            string text = "In file " + index.ToString() + "\r\n";

            string fileName = "thefile" + index.ToString("00") + ".txt";
            string filePath = folder + fileName;

            byte[] encodedText = Encoding.Unicode.GetBytes(text);

            FileStream sourceStream = new FileStream(filePath,
                FileMode.Append, FileAccess.Write, FileShare.None,
                bufferSize: 4096, useAsync: true);

            Task theTask = sourceStream.WriteAsync(encodedText, 0, encodedText.Length);
            sourceStreams.Add(sourceStream);

            tasks.Add(theTask);
        }

        await Task.WhenAll(tasks);
    }

    finally
    {
        foreach (FileStream sourceStream in sourceStreams)
        {
            sourceStream.Close();
        }
    }
}

Wenn Sie die WriteAsync und ReadAsync-Methoden, können Sie CancellationToken angeben, die Sie verwenden können, um den Vorgangsmittelstrahl abzubrechen. Weitere Informationen finden Sie unter Feinabstimmung der Async-Anwendung (C# und Visual Basic) und Abbruch in verwalteten Threads.

Siehe auch

Aufgaben

Exemplarische Vorgehensweise: Verwenden des Debuggers mit Async-Methoden

Konzepte

Asynchrone Programmierung mit Async und Await (C# und Visual Basic)

Asynchrone Rückgabetypen (C# und Visual Basic)

Ablaufsteuerung in asynchronen Programmen (C# und Visual Basic)