Tevékenység lemondása

Az System.Threading.Tasks.Task és System.Threading.Tasks.Task<TResult> az osztályok a lemondási jogkivonatok használatával támogatják a lemondást. További információ: Lemondás felügyelt szálakban. A feladatosztályokban a lemondás magában foglalja a felhasználói meghatalmazott együttműködését, amely egy lemondható műveletet jelöl, valamint a lemondást kérő kód között. A sikeres lemondás magában foglalja a metódus meghívását CancellationTokenSource.Cancel kérő kódot, és a felhasználó delegáltja időben megszakítja a műveletet. A műveletet az alábbi lehetőségek egyikével fejezheti be:

  • A meghatalmazotttól való visszatéréssel. Ez a lehetőség sok esetben elegendő. A megszakított feladatpéldányok azonban nem az állapotra, hanem az TaskStatus.RanToCompletion állapotra váltanak TaskStatus.Canceled át.

  • A jogkivonat eldobásával OperationCanceledException és átadásával, amelyre a lemondást kérték. A módszer használatának elsődleges módja a ThrowIfCancellationRequested módszer használata. Az ily módon megszakított feladat a Mégse állapotra vált, amellyel a hívókód ellenőrizheti, hogy a tevékenység válaszolt-e a lemondási kérésére.

Az alábbi példa a kivételt okozó tevékenységtörlés alapmintáját mutatja be:

Feljegyzés

A jogkivonatot a rendszer átadja a felhasználó delegáltjának és a feladatpéldánynak.

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

Egy teljes példáért lásd : Feladat megszakítása és gyermekei.

Amikor egy feladatpéldány megfigyel egy OperationCanceledException felhasználói kód által küldött hibát, összehasonlítja a kivétel jogkivonatát a társított jogkivonattal (amely a feladatot létrehozó API-nak lett átadva). Ha a jogkivonatok azonosak, és a jogkivonat tulajdonsága IsCancellationRequested visszaadja true, a feladat ezt úgy értelmezi, mint a lemondást és a Mégse állapotra való áttérést. Ha nem használ vagy WaitAll nem használ metódust Wait a tevékenységre való várakozáshoz, akkor a tevékenység csak az állapotát Canceledállítja be.

Ha olyan tevékenységre vár, amely a Mégse állapotra vált, a rendszer kivételt System.Threading.Tasks.TaskCanceledException (kivételbe AggregateException csomagolt) dob. Ez a kivétel a hibás helyzet helyett a sikeres lemondást jelzi. Ezért a tevékenység tulajdonsága Exception ad vissza null.

Ha a jogkivonat tulajdonsága IsCancellationRequested visszaadja false , vagy ha a kivétel jogkivonata nem egyezik meg a Tevékenység jogkivonatával, a OperationCanceledException rendszer normál kivételként kezeli, így a tevékenység hibás állapotba vált. Az egyéb kivételek jelenléte azt is eredményezi, hogy a tevékenység hibás állapotba vált. A tulajdonságban Status lekérheti a befejezett tevékenység állapotát.

Előfordulhat, hogy egy feladat a lemondás kérése után is feldolgoz bizonyos elemeket.

Lásd még