Annullamento delle attivitàTask Cancellation

Le classi System.Threading.Tasks.Task e System.Threading.Tasks.Task<TResult> supportano l'annullamento tramite l'utilizzo dei token di annullamento in .NET Framework.The System.Threading.Tasks.Task and System.Threading.Tasks.Task<TResult> classes support cancellation through the use of cancellation tokens in the .NET Framework. Per altre informazioni, vedere Annullamento in thread gestiti.For more information, see Cancellation in Managed Threads. 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.In the Task classes, cancellation involves cooperation between the user delegate, which represents a cancelable operation and the code that requested the cancellation. 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.A successful cancellation involves the requesting code calling the CancellationTokenSource.Cancel method, and the user delegate terminating the operation in a timely manner. L'operazione può essere interrotta tramite una di queste opzioni:You can terminate the operation by using one of these options:

  • Completare l'esecuzione del delegato.By simply returning from the delegate. In molti scenari questo approccio è sufficiente. Tuttavia, un'istanza di attività "annullata" in questo modo passa allo stato TaskStatus.RanToCompletion , non allo stato TaskStatus.Canceled .In many scenarios this is sufficient; however, a task instance that is canceled in this way transitions to the TaskStatus.RanToCompletion state, not to the TaskStatus.Canceled state.

  • Generare un oggetto OperationCanceledException e passare a quest'ultimo il token in cui è stato richiesto l'annullamento.By throwing a OperationCanceledException and passing it the token on which cancellation was requested. Il modo preferito per eseguire queste operazioni è tramite il metodo ThrowIfCancellationRequested .The preferred way to do this is to use the ThrowIfCancellationRequested method. Un'attività annullata in questo modo passa allo stato Canceled. Il codice chiamante può usare tale stato per verificare che l'attività ha risposto alla richiesta di annullamento.A task that is canceled in this way transitions to the Canceled state, which the calling code can use to verify that the task responded to its cancellation request.

Nell'esempio seguente viene mostrato il modello di base relativo all'annullamento di attività che genera l'eccezione.The following example shows the basic pattern for task cancellation that throws the exception. Notare che il token viene passato al delegato dell'utente e all'istanza di attività stessa.Note that the token is passed to the user delegate and to the task instance itself.

using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        var tokenSource2 = new CancellationTokenSource();
        CancellationToken ct = tokenSource2.Token;

        var task = Task.Run(() =>
        {
            // 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 Task.Run.

        tokenSource2.Cancel();

        // Just continue on this thread, or await with try-catch:
        try
        {
            await task;
        }
        catch (OperationCanceledException e)
        {
            Console.WriteLine($"{nameof(OperationCanceledException)} thrown with message: {e.Message}");
        }
        finally
        {
            tokenSource2.Dispose();
        }

        Console.ReadKey();
    }
}
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
        Finally
           tokenSource2.Dispose()
        End Try

        Console.ReadKey()
    End Sub
End Module

Per un esempio più esaustivo, vedere Procedura: Annullare un'attività e i relativi figli.For a more complete example, see How to: Cancel a Task and Its Children.

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à.When a task instance observes an OperationCanceledException thrown by user code, it compares the exception's token to its associated token (the one that was passed to the API that created the Task). 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.If they are the same and the token's IsCancellationRequested property returns true, the task interprets this as acknowledging cancellation and transitions to the Canceled state. Se non si usa un metodo Wait o WaitAll per attendere l'attività, quest'ultima si limita a impostare il proprio stato su Canceled.If you do not use a Wait or WaitAll method to wait for the task, then the task just sets its status to Canceled.

Se si resta in attesa di un'attività che effettua la transizione allo stato Canceled, viene generata un'eccezione System.Threading.Tasks.TaskCanceledException (di cui viene eseguito il wrapping in un'eccezione AggregateException ).If you are waiting on a Task that transitions to the Canceled state, a System.Threading.Tasks.TaskCanceledException exception (wrapped in an AggregateException exception) is thrown. Notare che questa eccezione non indica una situazione di errore, bensì l'esito positivo di un annullamento.Note that this exception indicates successful cancellation instead of a faulty situation. Di conseguenza la proprietà Exception dell'attività restituisce null.Therefore, the task's Exception property returns 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.If the token's IsCancellationRequested property returns false or if the exception's token does not match the Task's token, the OperationCanceledException is treated like a normal exception, causing the Task to transition to the Faulted state. Notare inoltre che anche la presenza di altre eccezioni comporterà il passaggio dell'attività allo stato Faulted.Also note that the presence of other exceptions will also cause the Task to transition to the Faulted state. È possibile ottenere lo stato dell'attività completata nella proprietà Status .You can get the status of the completed task in the Status property.

È possibile che un'attività continui a elaborare alcuni elementi dopo la richiesta di annullamento.It is possible that a task may continue to process some items after cancellation is requested.

Vedere ancheSee also