async / await și Task în C# (.NET)

Execută operațiuni I/O neblocante (rețea, baze de date, fișiere) și coordonează sarcini concurente cu Task și Task.WhenAll.

Sintaxă C#
public async Task<T> MetodaAsync(CancellationToken ct = default) { var rez = await OperatieAsync(ct); return rez; }

Ce face async / await și Task<T>

Modelul async / await din C# permite scrierea codului asincron neblocant la fel de simplu și lizibil ca cel sincron. Atunci când o metodă marcată cu async întâlnește expresia await pe o operațiune I/O (interogare în baza de date, apel HTTP, citire din fișier), firul de execuție curent (thread-ul) nu este blocat în așteptarea răspunsului, ci este eliberat imediat în Thread Pool pentru a procesa alte cereri. Când operațiunea I/O se finalizează, execuția metodei continuă exact de la linia următoare.

O metodă async returnează aproape întotdeauna Task (când nu returnează o valoare, echivalentul asincron al lui void) sau Task<T> (când returnează o valoare de tip T). Prin convenție în .NET, toate metodele asincrone au sufixul Async (de exemplu GetUserAsync) și acceptă opțional un CancellationToken pentru anularea cooperativă a operațiunii.

Parametri, metode și opțiuni

Parametru / Metodă Descriere
Task / Task<T> Reprezintă o operațiune asincronă în curs de desfășurare care nu returnează valoare (Task) sau produce un rezultat de tip T (Task<T>).
async / await Modificatorul async activează cuvântul cheie await în metodă; await suspendă neblocant metoda până la finalizarea Task-ului.
Task.WhenAll(t1, t2, ...) Așteaptă în paralel finalizarea tuturor sarcinilor primite și returnează un tablou cu rezultatele lor.
Task.Delay(int ms, CancellationToken ct) Creează o pauză asincronă neblocantă (echivalentul asincron al lui Thread.Sleep).
ValueTask<T> Alternativă de tip structură la Task<T> care evită alocarea pe heap când rezultatul este adesea disponibil sincron (din cache).
CancellationToken Token propagat către metodele Async pentru a opri imediat operațiunea dacă utilizatorul sau apelantul a anulat cererea.

Exemple

Exemplul 1: Apel asincron secvențial vs. rulare în paralel cu Task.WhenAll

Dacă două apeluri asincrone nu depind unul de celălalt, le pornim simultan și le așteptăm cu await Task.WhenAll(...): timpul total va fi dat de cea mai lentă sarcină, nu de suma lor.

using System.Diagnostics;

var sw = Stopwatch.StartNew();

// Pornim toate cele 3 operațiuni I/O simultan:
Task<string> tProfil = IncarcaDateAsync("Profil utilizator", 120);
Task<string> tComenzi = IncarcaDateAsync("Ultimele comenzi", 150);
Task<string> tNotificari = IncarcaDateAsync("Notificări", 100);

string[] rezultate = await Task.WhenAll(tProfil, tComenzi, tNotificari);
sw.Stop();

foreach (string r in rezultate)
{
    Console.WriteLine(r);
}
Console.WriteLine($"Toate cele 3 cereri au fost completate în paralel (~{sw.ElapsedMilliseconds} ms < 370 ms).");

static async Task<string> IncarcaDateAsync(string resursa, int durataMs)
{
    await Task.Delay(durataMs); // simulează un apel I/O de rețea neblocant
    return $"[OK] {resursa} ({durataMs} ms)";
}

Ieșire în consolă

[OK] Profil utilizator (120 ms)
[OK] Ultimele comenzi (150 ms)
[OK] Notificări (100 ms)
Toate cele 3 cereri au fost completate în paralel (~155 ms < 370 ms).

Exemplul 2: Anularea unei operațiuni asincrone cu CancellationTokenSource

Configurăm un timeout automat de 80 ms cu CancellationTokenSource pentru a opri o operațiune care durează prea mult.

using var cts = new CancellationTokenSource(millisecondsDelay: 80);

try
{
    await ProcesareLungaAsync(cts.Token);
}
catch (OperationCanceledException)
{
    Console.WriteLine("Operațiunea a fost anulată deoarece a depășit limita de timp de 80 ms.");
}

static async Task ProcesareLungaAsync(CancellationToken ct)
{
    Console.WriteLine("Pornire descărcare raport...");
    await Task.Delay(500, ct);
    Console.WriteLine("Descărcare finalizată.");
}

Ieșire în consolă

Pornire descărcare raport...
Operațiunea a fost anulată deoarece a depășit limita de timp de 80 ms.

Greșeli frecvente

  • Declararea metodelor cu async void în loc de async Task: excepțiile aruncate într-o metodă async void nu pot fi prinse cu try / catch de apelant și prăbușesc întregul proces .NET! Singura excepție permisă pentru async void sunt event handler-ele din interfețele grafice (WPF/WinForms).
  • Blocarea sincronă pe cod asincron apelând task.Result sau task.Wait() în loc de await task — aceasta blochează firul de execuție curent (thread pool starvation) și poate cauza deadlock-uri.

Funcții și concepte înrudite

  • HttpClient (GetFromJsonAsync): Trimite cereri HTTP asincrone către API-uri REST și deserializează direct răspunsurile JSON cu metodele din System.Net.Http.Json.
  • File.ReadAllText / WriteAllTextAsync: Citește și scrie fișiere text sau linii pe disc (sincron și asincron) și construiește căi multi-platformă cu Path.Combine.
  • try / catch și using (IDisposable): Gestionează controlat excepțiile la rulare și eliberează garantat resursele externe (fișiere, conexiuni, stream-uri) prin IDisposable.