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 deasync Task: excepțiile aruncate într-o metodăasync voidnu pot fi prinse cutry / catchde apelant și prăbușesc întregul proces .NET! Singura excepție permisă pentruasync voidsunt event handler-ele din interfețele grafice (WPF/WinForms). - Blocarea sincronă pe cod asincron apelând
task.Resultsautask.Wait()în loc deawait 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.