Programação Assíncrona em C#: guia completo para iniciantes
\n\nProgramação assíncrona é um dos conceitos-chave do desenvolvimento moderno em C#. Ela permite que suas aplicações permaneçam responsivas, sem bloquear o fluxo de execução durante operações longas: leitura de arquivos, consultas a banco de dados ou chamadas HTTP. Neste guia, vamos explorar os fundamentos da assincronia em C# com exemplos práticos.
\n\nO que é programação assíncrona e por que ela é necessária?
\n\nNa programação síncrona, o código é executado sequencialmente. Se você chama um método que espera 5 segundos por uma resposta do servidor, toda a thread (UI ou de trabalho) congela. A aplicação "trava". A programação assíncrona resolve esse problema: em vez de bloquear a thread, o método retorna o controle ao código chamador e, quando o resultado estiver pronto, notifica sobre isso.
\n\nPrincipais vantagens da assincronia:
\n- \n
- Responsividade da UI — a interface não trava durante operações longas. \n
- Escalabilidade — aplicações servidoras podem processar mais requisições sem criar novas threads. \n
- Eficiência — threads liberadas são usadas para outras tarefas. \n
Fundamentos de async/await em C#
\n\nAs palavras-chave async e await são a base da programação assíncrona em C#. Elas foram introduzidas no C# 5.0 e tornaram o código assíncrono quase tão simples quanto o síncrono.
Regras de uso:
\n- \n
- O método é marcado com a palavra-chave
async. \n - O tipo de retorno deve ser
Task,Task<T>ouvoid(apenas para manipuladores de eventos). \n - Dentro do método, chame outros métodos assíncronos com a palavra-chave
await. \n
Exemplo simples:
\nusing System;\nusing System.Net.Http;\nusing System.Threading.Tasks;\n\nclass Program\n{\n static async Task Main(string[] args)\n {\n Console.WriteLine("Iniciando download...");\n string content = await DownloadWebPageAsync("https://example.com");\n Console.WriteLine($"Caracteres baixados: {content.Length}");\n }\n\n static async Task<string> DownloadWebPageAsync(string url)\n {\n using HttpClient client = new HttpClient();\n string result = await client.GetStringAsync(url);\n return result;\n }\n}\n\nObserve: o método Main também é marcado como async Task — isso é permitido a partir do C# 7.1.
Tipos Task, Task<T> e ValueTask
\n\nNa programação assíncrona em C#, são usados três tipos principais de valores de retorno:
\n\n- \n
Task— para métodos que não retornam valor (análogo a void). \n Task<T>— para métodos que retornam um valor do tipo T. \n ValueTask<T>— versão otimizada para cenários onde o resultado está frequentemente disponível de forma síncrona (por exemplo, a partir de cache). \n
Exemplo com Task<T>:
\nstatic async Task<int> CalculateSumAsync(int a, int b)\n{\n await Task.Delay(1000); // Simulação de trabalho longo\n return a + b;\n}\n\n// Chamada:\nint result = await CalculateSumAsync(5, 3);\nConsole.WriteLine(result); // 8\n\nTratamento de erros em métodos assíncronos
\n\nExceções em métodos assíncronos são tratadas com o bloco padrão try-catch. No entanto, há uma nuance importante: a exceção é armazenada no objeto Task e "relançada" ao usar await.
static async Task<string> ReadFileAsync(string path)\n{\n try\n {\n string content = await File.ReadAllTextAsync(path);\n return content;\n }\n catch (FileNotFoundException ex)\n {\n Console.WriteLine($"Arquivo não encontrado: {ex.Message