Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Você pode usar o recurso Assíncrono para acessar arquivos. Usando o recurso Assíncrono, você pode chamar métodos assíncronos sem usar retornos de chamada ou dividir seu código em vários métodos ou expressões lambda. Para tornar o código síncrono assíncrono, basta chamar um método assíncrono em vez de um método síncrono e adicionar algumas palavras-chave ao código.
Você pode considerar os seguintes motivos para adicionar assincronia às chamadas de acesso a arquivos:
A assincronia torna os aplicativos da interface do usuário mais responsivos porque o thread da interface do usuário que inicia a operação pode executar outro trabalho. Se o thread da interface do usuário precisar executar um código que leva muito tempo (por exemplo, mais de 50 milissegundos), a interface do usuário poderá congelar até que a E/S seja concluída e o thread da interface do usuário possa processar novamente a entrada do teclado e do mouse e outros eventos.
A assincronia melhora a escalabilidade de ASP.NET e outros aplicativos baseados em servidor, reduzindo a necessidade de threads. Se o aplicativo usa um thread dedicado por resposta e mil solicitações estão sendo tratadas simultaneamente, mil threads são necessários. As operações assíncronas geralmente não precisam usar um thread durante a espera. Eles usam o thread de conclusão de E/S existente brevemente no final.
A latência de uma operação de acesso a arquivos pode ser muito baixa nas condições atuais, mas a latência pode aumentar muito no futuro. Por exemplo, um arquivo pode ser movido para um servidor que está em todo o mundo.
A sobrecarga adicional de usar o recurso assíncrono é pequena.
As tarefas assíncronas podem ser facilmente executadas em paralelo.
Executando os exemplos
Para executar os exemplos neste tópico, você pode criar um aplicativo WPF ou um aplicativo Windows Forms e, em seguida, adicionar um botão. No evento do botão Click, adicione uma chamada ao primeiro método em cada exemplo.
Nos exemplos a seguir, inclua as seguintes instruções Imports.
Imports System
Imports System.Collections.Generic
Imports System.Diagnostics
Imports System.IO
Imports System.Text
Imports System.Threading.Tasks
Uso da classe FileStream
Os exemplos neste tópico usam a FileStream classe, que tem uma opção que faz com que a E/S assíncrona ocorra no nível do sistema operacional. Usando essa opção, você pode evitar bloquear um thread ThreadPool em muitos casos. Para habilitar esta opção, especifique o argumento useAsync=true ou options=FileOptions.Asynchronous na chamada do construtor.
Você não pode usar essa opção com StreamReader e StreamWriter se abri-los diretamente especificando um caminho de arquivo. No entanto, você pode usar essa opção se fornecer a eles um Stream que a FileStream classe abriu. Observe que as chamadas assíncronas são mais rápidas em aplicativos de interface do usuário, mesmo que um thread ThreadPool esteja bloqueado, porque o thread da interface do usuário não é bloqueado durante a espera.
Escrever texto
O exemplo a seguir grava texto em um arquivo. A cada instrução await, o método é encerrado imediatamente. Quando a E/S do arquivo estiver concluída, o método será retomado na instrução que segue a instrução await. Observe que o modificador async está na definição de métodos que usam a instrução 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
O exemplo original tem a afirmação Await sourceStream.WriteAsync(encodedText, 0, encodedText.Length), que é uma contração das duas afirmações a seguir:
Dim theTask As Task = sourceStream.WriteAsync(encodedText, 0, encodedText.Length)
Await theTask
A primeira instrução retorna uma tarefa e faz com que o processamento do arquivo seja iniciado. A segunda instrução com o await faz com que o método saia imediatamente e retorne uma tarefa diferente. Quando o processamento do arquivo for concluído, a execução retornará à instrução que se segue ao await. Para obter mais informações, consulte Fluxo de controle em programas assíncronos (Visual Basic).
Leitura de Texto
O exemplo a seguir lê o texto de um arquivo. O texto é armazenado em buffer e, neste caso, colocado em StringBuilder. Ao contrário do exemplo anterior, a avaliação do await produz um valor. O ReadAsync método retorna um Task<Int32>, de modo que a avaliação do await produz um Int32 valor (numRead) após a conclusão da operação. Para obter mais informações, consulte Tipos de retorno assíncronos (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
E/S assíncronas paralelas
O exemplo a seguir demonstra o processamento paralelo gravando 10 arquivos de texto. Para cada arquivo, o WriteAsync método retorna uma tarefa que é adicionada a uma lista de tarefas. A instrução Await Task.WhenAll(tasks) sai do método e retoma a execução dentro do método quando o processamento do ficheiro é concluído para todas as tarefas.
O exemplo fecha todas as instâncias de FileStream num bloco de Finally depois de as tarefas serem concluídas. Se cada FileStream fosse criado numa instrução Imports, o FileStream poderia ser descartado antes que a tarefa fosse concluída.
Observe que qualquer aumento de desempenho é quase inteiramente do processamento paralelo e não do processamento assíncrono. As vantagens da assincronia são que ela não bloqueia vários processos e também não bloqueia o processo da interface de utilizador.
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
Ao usar os métodos WriteAsync e ReadAsync, pode especificar um CancellationToken, que pode ser usado para cancelar a operação a meio. Para obter mais informações, consulte Fine-Tuning A Sua Aplicação Assíncrona (Visual Basic) e Cancelamento em Threads Geridos.