Usando o Async para acessar arquivos (C# e Visual Basic)

Você pode usar o recurso de Async para acessar arquivos.Usando o recurso de async, você pode chamar em métodos assíncronos sem usar retornos de chamada ou dividir seu código entre vários métodos ou expressões lambda.Para tornar o código síncrono assíncrona, você apenas chama um método assíncrono em vez de um método síncrona e adiciona alguns palavra-chave ao código.

Você pode ver as seguintes razões para adicionar asynchrony para chamadas de acesso ao arquivo:

  • Asynchrony torna aplicativos de interface do usuário mais responsivo porque o encadeamento de interface do usuário que inicia a operação pode executar outro trabalho.Se o encadeamento de interface de usuário deve executar o código que demora para (por exemplo, mais de 50 milissegundos), a interface do usuário pode congelar até que E/S seja concluída e o encadeamento de interface do usuário pode novamente processar a entrada de teclado e mouse e os outros eventos.

  • Asynchrony melhorar a escalabilidade do ASP.NET e de outros aplicativos baseados no servidor reduzindo a necessidade de segmentos.Se o aplicativo usa um segmento dedicado pela resposta e milhar solicitações estão sendo tratados simultaneamente, separador segmentos são necessários.Operações assíncronas geralmente não precisa usar uma thread durante a espera.Usam o segmento existente de conclusão de E/S rapidamente no final.

  • A latência de uma operação de acesso ao arquivo pode ser condições atuais inferiores muito monitores, mas a latência pode aumentar aumentar no futuro.Por exemplo, um arquivo pode ser movido para um servidor que é através do mundo.

  • A sobrecarga adicional de usar o recurso de Async é pequena.

  • As tarefas assíncronos podem facilmente ser executadas paralelamente.

Executando os exemplos

ObservaçãoObservação

Os exemplos em este tópico não se aplicam aos Windows Store apps, que são apps de Windows 8 que são tela inteira e personalizado para a interação de contato.Para obter informações sobre como usar o acesso ao arquivo de async em apps de Windows Store , consulte Visão geral dos aplicativos .NET para Windows Store e E/S de arquivo e de fluxo.Para exemplos de E/S de arquivo para apps de Windows Store , você pode baixar Exemplo de acesso a arquivos.

Para rodar os exemplos em este tópico, você pode criar Aplicativo WPF ou Aplicativo de Windows Forms e adicionar Botão.Em o evento de Click do botão, adicione uma chamada para o primeiro método em cada exemplo.

Em os exemplos a seguir, inclua o seguinte Imports (Visual Basic) ou instruções de using (C#).

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;

Uso da classe de FileStream

Os exemplos em este tópico usam a classe de FileStream , que tem uma opção que faz com que E/S assíncrona ocorra no nível do sistema operacional.Usando essa opção, você pode evitar bloquear um segmento de ThreadPool em muitos casos.Para ativar essa opção, você especifica o argumento de useAsync=true ou de options=FileOptions.Asynchronous na chamada de construtor.

Você não pode usar esta opção com StreamReader e StreamWriter se você o abre diretamente especificando um caminho de arquivo.Em o entanto, você pode usar esta opção se eles Stream que você fornece a classe de FileStream abriu.Observe que as chamadas assíncronas são mais rápidas em apps de interface do usuário mesmo se um segmento de ThreadPool é bloqueado, porque o encadeamento de interface de usuário não está bloqueado durante a espera.

Texto de gravação

O exemplo escreve texto em um arquivo.Em cada aguardar a instrução, o método sai imediatamente.Quando o arquivo I/O está concluída, o método continua na declaração que segue a declaração de espera.Observe que o modificador de async está na definição dos métodos que usam a instrução de espera.

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

O exemplo original tem a instrução await sourceStream.WriteAsync(encodedText, 0, encodedText.Length);, que é uma contração das duas instruções:

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

A primeira declaração retorna uma tarefa e faz com que o processamento de arquivo para o início.A segunda instrução com a espera faz com que o método imediatamente à saída e retorna uma tarefa diferente.Quando o processamento de arquivo termina posteriormente, a execução retorna a declaração que segue a espera.Para obter mais informações, consulte Fluxo de controle em programas Async (C# e Visual Basic) e Passo a passo: Usando o depurador com métodos assíncronos.

Texto de leitura

O exemplo a seguir lê o texto de um arquivo.O texto são armazenados em buffer e, em esse caso, colocado em StringBuilder.A o contrário no exemplo anterior, a avaliação de espera gera um valor.O método de ReadAsync retorna Task<Int32>, então a avaliação de espera gera um valor de Int32 (numRead) após a conclusão da operação.Para obter mais informações, consulte Tipos de retorno de Async (C# e 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();
    }
}

E/S assíncrona paralelo

O exemplo demonstra o processamento paralelo 10 para gravar arquivos de texto.Para cada arquivo, o método de WriteAsync retorna uma tarefa que é adicionada a uma lista de tarefas.A declaração de await Task.WhenAll(tasks); sai do método e continuar-lo no método quando o processamento de arquivo está completo para todas as tarefas.

O exemplo fecha todas as instâncias de FileStream em um bloco de finally após as tarefas são completas.Se cada FileStream foi criado em vez em uma declaração de using , FileStream pode ser descartado antes que a tarefa foi concluída.

Observe que qualquer aumento de desempenho é quase inteiramente de processamento paralelo e não de processamento assíncrono.As vantagens de asynchrony que não são cadeia de caracteres anterior vários segmentos, e não cadeia de caracteres anterior o encadeamento de interface do usuário.

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

A o usar os métodos de WriteAsync e de ReadAsync , você pode especificar CancellationToken, que você pode usar para cancelar o meados de- fluxo da operação.Para obter mais informações, consulte Ajustando seu aplicativo Async (C# e Visual Basic) e Cancelamento em Threads gerenciados.

Consulte também

Tarefas

Passo a passo: Usando o depurador com métodos assíncronos

Conceitos

Programação com Async assíncrona e esperar (C# e Visual Basic)

Tipos de retorno de Async (C# e Visual Basic)

Fluxo de controle em programas Async (C# e Visual Basic)