Concorrência e Multithreading em C#: Guia Completo

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Concorrência e Multithreading em C#: Um Guia Completo

Aplicações modernas exigem alta performance e capacidade de resposta. Concorrência e multithreading em C# são ferramentas essenciais que permitem executar múltiplas tarefas simultaneamente, usar eficientemente processadores multi-core e melhorar a experiência do usuário. Neste artigo, vamos detalhar os conceitos principais, começando por threads clássicas e terminando com async/await moderno e Parallel LINQ.



Fundamentos do Multithreading: A Classe Thread e o Thread Pool

Multithreading em C# começa com a classe System.Threading.Thread. Cada thread representa um caminho de execução separado dentro de um processo. No entanto, criar threads manualmente é uma operação cara. Para otimização, utiliza-se o thread pool (ThreadPool), que gerencia a reutilização de threads.

Exemplo de criação manual de uma thread:

using System;using System.Threading;

class Program{ static void Main() { Thread thread = new Thread(DoWork); thread.Start(); Console.WriteLine("A thread principal está trabalhando..."); thread.Join(); // Aguardar a conclusão }

static void DoWork() { Console.WriteLine("A thread está realizando trabalho."); }}

Para uso mais simples, recomenda-se ThreadPool:

ThreadPool.QueueUserWorkItem(state => {    Console.WriteLine("Tarefa no thread pool.");});

Importante: A classe Thread tem uma API de baixo nível e não suporta retornar um resultado. Para aplicações modernas, utilize Task.



Task e TPL (Task Parallel Library)

A biblioteca TPL (System.Threading.Tasks) fornece uma abstração de alto nível — Task. Uma Task representa uma operação assíncrona que pode retornar um valor. Esta é a base para a concorrência moderna em C#.

Exemplo de uma Task sem valor de retorno:

using System;using System.Threading.Tasks;

class Program{ static async Task Main() { Task task = Task.Run(() => DoWork()); await task; Console.WriteLine("Concluído."); }

static void DoWork() { Console.WriteLine("Trabalho em Task."); }}

Task com valor de retorno:

Task<int> task = Task.Run(() => {    int result = 0;    for (int i = 0; i < 1000000; i++) result += i;    return result;});int sum = await task;Console.WriteLine($"Soma: {sum}");

TPL também inclui Parallel.For e Parallel.ForEach para processamento paralelo de coleções:

Parallel.For(0, 10, i => {    Console.WriteLine($"Iteração {i} na thread {Thread.CurrentThread.ManagedThreadId}");});


Async/await: Programação Assíncrona

As palavras-chave async e await simplificam a escrita de código assíncrono, fazendo-o parecer com código síncrono. Elas não criam novas threads, mas alternam eficientemente o contexto de execução, liberando a thread para outras tarefas.

Exemplo de um método assíncrono:

using System;using System.Net.Http;using System.Threading.Tasks;

class Program{ static async Task Main() { string data = await FetchDataAsync("https://example.com"); Console.WriteLine(data); }

static async Task<string> FetchDataAsync(string url) { using HttpClient client = new HttpClient(); string result = await client.GetStringAsync(url); return result; }}

Regras de uso:

  • Um método com async deve retornar Task, Task<T> ou void (apenas para manipuladores de eventos

Blogs

Book Recommendations