Udostępnij za pośrednictwem


Użycie Async do uzyskiwania dostępu do plików (C# i Visual Basic)

Można użyć Async funkcji uzyskać dostęp do plików.Za pomocą funkcji komunikacji asynchronicznej, można wywoływać metody asynchronicznej bez za pomocą wywołania zwrotne lub dzielenie kodu wielu metod lub wyrażenia lambda.Aby kod synchroniczne asynchronicznych, możesz tylko wywołania metod asynchronicznych, zamiast metody synchroniczne i dodać kilka słów kluczowych do kodu.

Warto rozważyć następujące powody Dodawanie asynchrony do wywołania dostępu do pliku:

  • Asynchrony czyni interfejsu użytkownika aplikacji sprawniejszego ponieważ wątek interfejsu użytkownika, który uruchamia operację można wykonać inne prace.Jeśli wątek interfejsu użytkownika, należy wykonać kod który zabiera dużo czasu (na przykład więcej niż 50 milisekund), interfejsu użytkownika może zablokować aż wyjścia jest kompletny i wątku interfejsu użytkownika można ponownie procesu klawiatury i myszy wejściowych i innych zdarzeń.

  • Asynchrony zwiększa skalowalność ASP.NET i inne aplikacje oparte na serwerze, zmniejszając potrzebę wątków.Jeśli aplikacja używa dedykowanego wątku dla odpowiedzi i żądań tysiąc są obsługiwane jednocześnie, tysiąc wątki są potrzebne.Operacje asynchroniczne często nie trzeba używać podczas oczekiwania wątku.Używają istniejącego wątku zakończenia We/Wy z krótko na końcu.

  • Czas oczekiwania operacji dostępu do pliku może być bardzo niski w obecnych warunkach, ale opóźnienie może znacznie zwiększyć w przyszłości.Na przykład plik może być przemieszczane do serwera, który jest na całym świecie.

  • Dodano z używaniem funkcji komunikacji asynchronicznej jest mała.

  • Zadania asynchroniczne można łatwo uruchamiać równolegle.

Uruchamianie przykładów

[!UWAGA]

Przykłady w tym temacie nie stosuje się do Windows Store aplikacje, które są Windows 8 aplikacje, które są pełnego ekranu i dostosowane do potrzeb touch interakcji.Informacji na temat async dostęp do plików w Windows Store aplikacji, zobacz .NET for Windows Store apps overview i Plik i strumień we/wy.Przykłady we/wy dla plików Windows Store aplikacje, można pobrać Próbki dostępu pliku.

Aby uruchomić przykłady w tym temacie, można utworzyć Aplikacji WPF lub Aplikacji Windows Forms , a następnie dodać przycisku.Przycisk Click zdarzenie, dodać wywołanie metody pierwszego przykładu.

W poniższych przykładach obejmują następujące Imports (Visual Basic) lub using (C#) oświadczenia.

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;

Użyj klasy FileStream

Przykłady w tym temacie FileStream klasy opcji, powodujący asynchronicznego wejścia/wyjścia występuje na poziomie systemu operacyjnego.Za pomocą tej opcji, można uniknąć blokowania wątek puli wątków w wielu przypadkach.Aby włączyć tę opcję, należy określić useAsync=true lub options=FileOptions.Asynchronous argument w wywołaniu konstruktora.

Nie można użyć tej opcji z StreamReader i StreamWriter Jeśli otworzyć bezpośrednio, określając ścieżkę pliku.Jednak można użyć tej opcji, jeśli je dostarczyć Stream , FileStream klasy otwarty.Należy zauważyć, że wywołania asynchroniczne szybciej w interfejsie użytkownika aplikacji, nawet jeśli wątek puli wątków jest zablokowany, ponieważ wątek interfejsu użytkownika nie jest blokowane podczas oczekiwania.

Pisanie tekstu

Poniższy przykład zapisuje w pliku tekstowym.Poczekać na każdej instrukcji, metodą natychmiast zamyka.Po zakończeniu we/wy pliku metody wznawia na stwierdzenie, że wynika z instrukcji await.Zauważ, że modyfikator asynchronicznej w definicji metody, które należy użyć instrukcji await.

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);
    };
}

Przykład oryginalnego ma instrukcja await sourceStream.WriteAsync(encodedText, 0, encodedText.Length);, który jest dwie poniższe instrukcje:

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

Pierwsza instrukcja zwraca zadania i powoduje przetwarzanie pliku rozpocząć.Druga instrukcja z await powoduje, że metoda natychmiast Zakończ i powróć różnych zadań.Po zakończeniu przetwarzania później plików wykonanie zwraca się do instrukcji, który następuje await.Aby uzyskać więcej informacji, zobacz Przepływ sterowania w programach Async (C# i Visual Basic) i Wskazówki: Korzystanie z debugera i metod asynchronicznych.

Czytanie tekstu

Poniższy przykład odczytuje tekst z pliku.Tekst buforowane i umieszczane w przypadku StringBuilder.W przeciwieństwie do poprzedniego przykładu oceny await tworzy wartość.ReadAsync Metoda zwraca Task<Int32>, co daje oceny await Int32 wartość (numRead) po zakończeniu operacji.Aby uzyskać więcej informacji, zobacz Typy zwrotu Async (C# i 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();
    }
}

Równoległe asynchronicznego wejścia/wyjścia

Poniższy przykład ilustruje przetwarzanie równoległe, pisząc 10 plików tekstowych.Dla każdego pliku WriteAsync metoda zwraca zadanie, które jest następnie dodany do listy zadań.await Task.WhenAll(tasks); Instrukcji zamyka metody i wznawia w metodzie podczas przetwarzania pliku jest wykonać wszystkie zadania.

Przykład zamyka wszystkie FileStream wystąpień w finally zablokować po zakończeniu zadania.Jeśli każdy FileStream zamiast został utworzony w using instrukcji, FileStream może zostać usunięte przed zadaniem jest kompletna.

Zauważ, że wszelkie podniesienie wydajności niemal całkowicie z przetwarzania równoległego i przetwarzania asynchronicznego.Zalety asynchrony są, że nie wiąże się wiele wątków i że go nie blokowały wątek interfejsu użytkownika.

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();
        }
    }
}

Podczas korzystania z WriteAsync i ReadAsync metod, można określić CancellationToken, którym można anulować mid-stream operacji.Aby uzyskać więcej informacji, zobacz Dostrajanie aplikacji Async (C# i Visual Basic) i Anulowanie w zarządzanych wątków.

Zobacz też

Zadania

Wskazówki: Korzystanie z debugera i metod asynchronicznych

Koncepcje

Asynchroniczne programowania przy użyciu asynchronicznej i poczekać (C# i Visual Basic)

Typy zwrotu Async (C# i Visual Basic)

Przepływ sterowania w programach Async (C# i Visual Basic)