Creare manualmente un Task da usare con async/await

di Cristian Civera, in .NET Framework,

I Task sono oggetti che rappresentano un'operazione che può avere uno stato di successo e di fallimento, e tramite il pattern async/await ci permettono facilmente di scrivere codice asincrono. Normalmente, poiché utilizziamo funzioni asincrone del .NET Framework o di WinRT, il nostro codice sfrutta le parole chiavi async/await per attendere e per restituire un nuovo Task che ne ingloba degli altri, ma non sempre questo è possibile.

Supponiamo, per esempio, di avere una Popup per mostrare delle informazioni all'utente, dandogli la possibilità con dei pulsanti di rispondere positivamente o negativamente. Il codice per realizzare questo in WinRT, e in maniera molto simile anche in WPF, è il seguente:

// Creo l'user control con l'interfaccia
var uc = new MyUserControl();
uc.yesButton.Click += (s, e) => {
    // TODO
};

// Mostro la popup
Popup popup = new Popup();
popup.Child = uc;
popup.IsOpen = true;

Per rendere più facile la programmazione, vogliamo a questo punto utilizzare i Task per mostrare la Popup e attendere il relativo responso. Inglobiamo quindi il codice precedente in una funzione che crea la Popup e restituisce un Task.

public static Task<bool> AskAsync()
{
    // ... codice precedente ...

    var source = new TaskCompletionSource<bool>();
    return source.Task;
}

Per farlo utilizziamo l'oggetto TaskCompletionSource che ci permette di avere l'oggetto Task e di controllarlo. I relativi metodi TrySetResult e TrySetCanceled ci permettono di completare il Task con successo o meno, permettendo di leggere il risultato e di proseguire per chi sta aspettando l'esito. Nello snippet seguente impostiamo il risultato alla pressione del pulsante .

uc.yesButton.Click += (s, e) => {
    source.TrySetResult(true);
};

A questo punto per mostrare la Popup non dobbiamo far altro che invocare la nostra funzione asincrona.

bool r = await Helper.AskAsync();
if (r)
{
    // Risposta positiva
}

Eventualmente, possiamo indicare un'eccezione mediante il metodo TrySetException.

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

I più letti di oggi