evento
Crie aplicativos e agentes de IA
17/03, 21 - 21/03, 10
Junte-se à série meetup para criar soluções de IA escaláveis com base em casos de uso do mundo real com outros desenvolvedores e especialistas.
Registe-se agoraEste browser já não é suportado.
Atualize para o Microsoft Edge para tirar partido das mais recentes funcionalidades, atualizações de segurança e de suporte técnico.
Pode utilizar a funcionalidade assíncrona para aceder a ficheiros. Ao utilizar a funcionalidade assíncrona, pode chamar métodos assíncronos sem utilizar chamadas de retorno ou dividir o 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.
Pode considerar os seguintes motivos para adicionar assíncrona a chamadas de acesso a ficheiros:
Os exemplos simples neste tópico demonstram File.WriteAllTextAsync e File.ReadAllTextAsync. Para controlar bem as operações de E/S do ficheiro, utilize a FileStream classe, que tem uma opção que faz com que a E/S assíncrona ocorra ao nível do sistema operativo. Ao utilizar esta opção, pode evitar bloquear um thread de conjunto de threads em muitos casos. Para ativar esta opção, especifique o useAsync=true
argumento ou options=FileOptions.Asynchronous
na chamada do construtor.
Não pode utilizar esta opção com StreamReader e StreamWriter se as abrir diretamente ao especificar um caminho de ficheiro. No entanto, pode utilizar esta opção se lhes indicar que Stream a classe abriu FileStream . As chamadas assíncronas são mais rápidas nas aplicações de IU, mesmo que um thread de conjunto de threads esteja bloqueado, porque o thread de IU não é bloqueado durante a espera.
Os exemplos seguintes escrevem texto num ficheiro. Em cada instrução de espera, o método sai imediatamente. Quando a E/S do ficheiro estiver concluída, o método é retomado na instrução que se segue à instrução await. O modificador assíncrono está na definição de métodos que utilizam a instrução await.
public async Task SimpleWriteAsync()
{
string filePath = "simple.txt";
string text = $"Hello World";
await File.WriteAllTextAsync(filePath, text);
}
public async Task ProcessWriteAsync()
{
string filePath = "temp.txt";
string text = $"Hello World{Environment.NewLine}";
await WriteTextAsync(filePath, text);
}
async Task WriteTextAsync(string filePath, string text)
{
byte[] encodedText = Encoding.Unicode.GetBytes(text);
using var sourceStream =
new FileStream(
filePath,
FileMode.Create, 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 seguintes:
Task theTask = sourceStream.WriteAsync(encodedText, 0, encodedText.Length);
await theTask;
A primeira instrução devolve uma tarefa e faz com que o processamento de ficheiros seja iniciado. A segunda instrução com a aguardação faz com que o método saia imediatamente e devolva uma tarefa diferente. Quando o processamento do ficheiro for concluído mais tarde, a execução regressa à instrução que se segue à espera.
Os exemplos seguintes leem texto de um ficheiro.
public async Task SimpleReadAsync()
{
string filePath = "simple.txt";
string text = await File.ReadAllTextAsync(filePath);
Console.WriteLine(text);
}
O texto está em memória intermédia e, neste caso, colocado num StringBuilder. Ao contrário do exemplo anterior, a avaliação da espera produz um valor. O ReadAsync método devolve um Task<>Int32, pelo que a avaliação da espera produz um Int32
valor numRead
após a conclusão da operação. Para obter mais informações, veja Async Return Types (C#).
public async Task ProcessReadAsync()
{
try
{
string filePath = "temp.txt";
if (File.Exists(filePath) != false)
{
string text = await ReadTextAsync(filePath);
Console.WriteLine(text);
}
else
{
Console.WriteLine($"file not found: {filePath}");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
async Task<string> ReadTextAsync(string filePath)
{
using var sourceStream =
new FileStream(
filePath,
FileMode.Open, FileAccess.Read, FileShare.Read,
bufferSize: 4096, useAsync: true);
var 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();
}
Os exemplos seguintes demonstram o processamento paralelo ao escrever 10 ficheiros de texto.
public async Task SimpleParallelWriteAsync()
{
string folder = Directory.CreateDirectory("tempfolder").Name;
IList<Task> writeTaskList = new List<Task>();
for (int index = 11; index <= 20; ++ index)
{
string fileName = $"file-{index:00}.txt";
string filePath = $"{folder}/{fileName}";
string text = $"In file {index}{Environment.NewLine}";
writeTaskList.Add(File.WriteAllTextAsync(filePath, text));
}
await Task.WhenAll(writeTaskList);
}
Para cada ficheiro, o WriteAsync método devolve uma tarefa que é adicionada a uma lista de tarefas. A await Task.WhenAll(tasks);
instrução sai do método e é retomada no método quando o processamento de ficheiros é concluído para todas as tarefas.
O exemplo fecha todas as FileStream instâncias num finally
bloco após a conclusão das tarefas. Se cada um FileStream
tiver sido criado numa using
instrução, poderá FileStream
ser eliminado antes de a tarefa ser concluída.
Qualquer aumento de desempenho é quase inteiramente do processamento paralelo e não do processamento assíncrono. As vantagens da assíncrona são que não liga vários threads e que não liga o thread da interface de utilizador.
public async Task ProcessMultipleWritesAsync()
{
IList<FileStream> sourceStreams = new List<FileStream>();
try
{
string folder = Directory.CreateDirectory("tempfolder").Name;
IList<Task> writeTaskList = new List<Task>();
for (int index = 1; index <= 10; ++ index)
{
string fileName = $"file-{index:00}.txt";
string filePath = $"{folder}/{fileName}";
string text = $"In file {index}{Environment.NewLine}";
byte[] encodedText = Encoding.Unicode.GetBytes(text);
var sourceStream =
new FileStream(
filePath,
FileMode.Create, FileAccess.Write, FileShare.None,
bufferSize: 4096, useAsync: true);
Task writeTask = sourceStream.WriteAsync(encodedText, 0, encodedText.Length);
sourceStreams.Add(sourceStream);
writeTaskList.Add(writeTask);
}
await Task.WhenAll(writeTaskList);
}
finally
{
foreach (FileStream sourceStream in sourceStreams)
{
sourceStream.Close();
}
}
}
Ao utilizar os WriteAsync métodos e ReadAsync , pode especificar um CancellationToken, que pode utilizar para cancelar a operação a meio do fluxo. Para obter mais informações, veja Cancelamento em threads geridos.
Comentários do .NET
O .NET é um projeto código aberto. Selecione um link para fornecer comentários:
evento
Crie aplicativos e agentes de IA
17/03, 21 - 21/03, 10
Junte-se à série meetup para criar soluções de IA escaláveis com base em casos de uso do mundo real com outros desenvolvedores e especialistas.
Registe-se agoraFormação
Módulo
Trabalhar com ficheiros e diretórios numa aplicação .NET - Training
Saiba como utilizar .NET, C# e System.IO para trabalhar com diretórios, caminhos, ficheiros e sistema de ficheiros.
Documentação
Processar tarefas assíncronas à medida que são concluídas - C#
Saiba como utilizar Task.WhenAny em C# para iniciar várias tarefas e processar os resultados à medida que terminam, em vez de processá-los pela ordem iniciada.
Gerar e consumir fluxos assíncronos - C#
Este tutorial avançado mostra como gerar e consumir fluxos assíncronos. Os fluxos assíncronos fornecem uma maneira mais natural de trabalhar com sequências de dados que podem ser geradas de forma assíncrona.
O modelo de Programação Assíncrona de Tarefas (TAP) com async and await" - C#
Saiba quando e como usar a programação assíncrona baseada em tarefas, uma abordagem simplificada para programação assíncrona em C#.