Threading & Synchronization
Thread vs Task, lock, SemaphoreSlim e Concurrent Collections em C#
Data races causam comportamento indefinido. Toda variavel mutavel compartilhada entre threads precisa de sincronizacao β
lock, Interlocked, ou colecoes concorrentes. Thread vs Task vs ThreadPool
Use Task (thread pool) para a maioria do trabalho paralelo. Thread bruto so quando voce precisa de controle de lifetime/afinidade.
| Aspecto | Thread | Task (ThreadPool) |
|---|---|---|
| Criacao | Cria thread do OS (~1MB stack) | Reutiliza threads do pool |
| Custo | Alto β criacao/destruicao caras | Baixo β pool gerencia lifecycle |
| Composicao | Ruim β sem await/continuacoes | Excelente β async/await nativo |
| Cancelamento | Manual (flags, Abort depreciado) | CancellationToken nativo |
| Quando usar | STA, afinidade de CPU, loops dedicados | CPU-bound, I/O-bound, tudo mais |
// Prefer Task for CPU-bound parallelism
Task t = Task.Run(() => DoCpuWork());
// Raw Thread only if you need OS thread control
var thread = new Thread(() => DoCpuWork()) { IsBackground = true };
thread.Start();
// Task uses the thread pool and composes well with async/await.
// Use Thread for special cases: STA, CPU affinity, long-lived dedicated loops.
Fluxo de sincronizacao
Blocking vs Async I/O
.Result e .Wait() bloqueiam uma thread enquanto esperam. Em ASP.NET isso desperdicar threads do pool e pode causar thread starvation. // BAD: Blocks a thread while waiting
string s = httpClient.GetStringAsync(url).Result;
// GOOD: Asynchronous, no thread blocked during I/O
string s2 = await httpClient.GetStringAsync(url);
// Blocking wastes a thread; prefer await for I/O.
Por que preferir Task.Run() a new Thread()?
Task.Run() usa o ThreadPool, que reutiliza threads ja existentes β sem custo de criacao/destruicao do OS. Alem disso, Task compoe com async/await, suporta CancellationToken, e propaga excecoes de forma estruturada. Thread bruto so faz sentido para cenarios especiais como threads STA ou loops de longa duracao dedicados.