Annullamento delle attività
Le classi System.Threading.Tasks.Task e System.Threading.Tasks.Task<TResult> supportano l'annullamento tramite l'utilizzo di una nuova funzionalità di .NET Framework 4, ovvero i token di annullamento. Per ulteriori informazioni, vedere Annullamento. Nelle classi Task l'annullamento comporta la cooperazione tra il delegato dell'utente, che rappresenta un'operazione annullabile, e il codice che ha richiesto l'annullamento. Un annullamento riuscito prevede una chiamata al metodo CancellationTokenSource.Cancel da parte del codice richiedente, nonché l'interruzione tempestiva dell'operazione da parte del delegato dell'utente. L'operazione può essere interrotta tramite una di queste opzioni:
Completare l'esecuzione del delegato. In molti scenari questo approccio è sufficiente. Tuttavia, un'istanza di attività "annullata" in questo modo passa allo stato RanToCompletion, non allo stato Canceled.
Generare un oggetto OperationCanceledException e passare a quest'ultimo il token in cui è stato richiesto l'annullamento. Il modo preferito per eseguire queste operazioni è tramite il metodo ThrowIfCancellationRequested. Un'attività annullata in questo modo passa allo stato Canceled. Il codice chiamante può utilizzare tale stato per verificare che l'attività ha risposto alla richiesta di annullamento.
Nell'esempio seguente viene mostrato il modello di base relativo all'annullamento di attività che genera l'eccezione. Notare che il token viene passato al delegato dell'utente e all'istanza di attività stessa.
Imports System.Threading
Imports System.Threading.Tasks
Module Test
Sub Main()
Dim tokenSource2 As New CancellationTokenSource()
Dim ct As CancellationToken = tokenSource2.Token
Dim t2 = Task.Factory.StartNew(Sub()
' Were we already canceled?
ct.ThrowIfCancellationRequested()
Dim moreToDo As Boolean = True
While moreToDo = True
' Poll on this property if you have to do
' other cleanup before throwing.
If ct.IsCancellationRequested Then
' Clean up here, then...
ct.ThrowIfCancellationRequested()
End If
End While
End Sub _
, tokenSource2.Token) ' Pass same token to StartNew.
' Cancel the task.
tokenSource2.Cancel()
' Just continue on this thread, or Wait/WaitAll with try-catch:
Try
t2.Wait()
Catch e As AggregateException
For Each item In e.InnerExceptions
Console.WriteLine(e.Message & " " & item.Message)
Next
End Try
Console.ReadKey()
End Sub
End Module
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static void Main()
{
var tokenSource2 = new CancellationTokenSource();
CancellationToken ct = tokenSource2.Token;
var task = Task.Factory.StartNew(() =>
{
// Were we already canceled?
ct.ThrowIfCancellationRequested();
bool moreToDo = true;
while (moreToDo)
{
// Poll on this property if you have to do
// other cleanup before throwing.
if (ct.IsCancellationRequested)
{
// Clean up here, then...
ct.ThrowIfCancellationRequested();
}
}
}, tokenSource2.Token); // Pass same token to StartNew.
tokenSource2.Cancel();
// Just continue on this thread, or Wait/WaitAll with try-catch:
try
{
task.Wait();
}
catch (AggregateException e)
{
foreach (var v in e.InnerExceptions)
Console.WriteLine(e.Message + " " + v.Message);
}
Console.ReadKey();
}
}
Per un esempio più esaustivo, vedere Procedura: annullare un'attività e i relativi figli.
Quando un'istanza dell'attività rileva un oggetto OperationCanceledException generato dal codice utente, confronta il token dell'eccezione con il token associato, ovvero il token passato all'API che ha creato l'attività. Se i due token sono uguali e la proprietà IsCancellationRequested del token restituisce true, ciò viene interpretato dall'attività come una conferma di annullamento e passa allo stato Canceled. Se non si utilizza un metodo Wait o WaitAll per attendere l'attività, quest'ultima si limita a impostare il proprio stato su Canceled.
Se si resta in attesa di un'attività che effettua la transizione allo stato Canceled, il sistema crea e genera un oggetto TaskCanceledException con wrapping in un oggetto AggregateException. Notare che questa eccezione non indica una situazione di errore, bensì l'esito positivo di un annullamento. Pertanto, la proprietà Exception dell'attività restituisce null.
Se la proprietà IsCancellationRequested del token restituisce false o se il token dell'eccezione non corrisponde a quello dell'attività, l'oggetto OperationCanceledException viene trattato come un'eccezione normale, il che comporta la transizione dell'attività allo stato Faulted. Notare inoltre che anche la presenza di altre eccezioni comporterà il passaggio dell'attività allo stato Faulted. È possibile ottenere lo stato dell'attività completata nella proprietà Status.
È possibile che un'attività continui a elaborare alcuni elementi dopo la richiesta di annullamento.
Vedere anche
Attività
Procedura: annullare un'attività e i relativi figli