loading experience

C#

async/await in C#: buone pratiche, Task e ValueTask

Gli errori più comuni con il codice asincrono e quando ha senso usare ValueTask.

async/await in C#: buone pratiche, Task e ValueTask

Il codice asincrono rende le applicazioni reattive e scalabili, ma qualche errore ricorrente può causare blocchi, eccezioni perse o prestazioni peggiori del codice sincrono.

Ogni livello attende il successivo e passa avanti il token di annullamento.
Ogni livello attende il successivo e passa avanti il token di annullamento.

Regola 1: asincrono fino in fondo

Bloccare un Task con .Result o .Wait() spreca thread e, in alcuni contesti, provoca deadlock. Se un metodo chiama codice asincrono, deve diventare asincrono anche lui.

// Da evitare
var cliente = repo.TrovaAsync(id).Result;

// Corretto
var cliente = await repo.TrovaAsync(id);

Regola 2: niente async void

Un metodo async void non può essere atteso e le sue eccezioni non si possono intercettare con un normale try/catch. Si usa solo per i gestori di eventi; in tutti gli altri casi restituisci Task.

Regola 3: propaga il CancellationToken

public async Task<Report> GeneraAsync(int anno, CancellationToken ct)
{
    var dati = await _repo.CaricaAsync(anno, ct);
    return await _calcolo.ElaboraAsync(dati, ct);
}

Così una richiesta web annullata dall'utente interrompe davvero il lavoro, invece di continuare a consumare risorse.

Quando usare ValueTask

ValueTask evita un'allocazione quando il risultato è spesso già disponibile, per esempio letto da una cache:

public ValueTask<Prodotto?> TrovaAsync(int id)
{
    if (_cache.TryGetValue(id, out var p))
        return ValueTask.FromResult<Prodotto?>(p); // nessuna allocazione

    return new ValueTask<Prodotto?>(CaricaDalDatabaseAsync(id));
}

Ma ha delle regole: un ValueTask si attende una sola volta e non va memorizzato per riusarlo. In caso di dubbio, Task resta la scelta più sicura; usa ValueTask solo dove una misura dimostra il vantaggio.

Commenti (0)

Nessun commento ancora.

Lascia un commento