Как отменить задачу с помощью CancellationToken?

Итак, у меня есть этот код:

//CancelationToken
CancellationTokenSource src = new CancellationTokenSource();
CancellationToken ct = src.Token;
ct.Register(() => Console.WriteLine("Abbruch des Tasks"));
//Task
Task t = new Task(() =>
{
    System.Threading.Thread.Sleep(1000);
    if (ct.IsCancellationRequested)
    {
        try
        {
            //Throw
            ct.ThrowIfCancellationRequested();                        
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine(
                "ThrowIfCancellationRequested() liefert eben eine Exception");
        }
    }             

}, ct);
//Run Task and Cancel
t.Start();
src.CancelAfter(350);
t.Wait();

// Get Information
Console.WriteLine("Canceled: {0} . Finished: {1} . Error: {2}",
                    t.IsCanceled, t.IsCompleted, t.IsFaulted);

Итак, в этом случае я отменил свою задачу, но в итоге я получил следующий результат: «Отменено: ложно. Завершено: верно. Ошибка: ложно».

На мой взгляд, это должно быть «Отменено: верно. Завершено: ложно». Почему я получаю такой результат? Потому что я пытаюсь поймать исключение?

Я пробовал это без блока try-catch, но затем моя программа останавливается из-за OperationCanceledException. Кто-нибудь может мне помочь?


person Netherstorm    schedule 24.02.2016    source источник
comment
Посмотрите здесь. Удалите try..catch и поместите его вокруг t.Wait(); по существу.   -  person Frank J    schedule 24.02.2016


Ответы (1)


Вы проглатываете исключение, поэтому задача помечается как завершенная, поскольку вы фактически обрабатываете исключение, и оно не распространяется наружу.

Вместо этого не перехватывайте исключение внутри делегата, перехватывайте его снаружи:

void Main()
{
    CancellationTokenSource src = new CancellationTokenSource();
    CancellationToken ct = src.Token;
    ct.Register(() => Console.WriteLine("Abbruch des Tasks"));

    Task t = Task.Run(() =>
    {
        System.Threading.Thread.Sleep(1000);
        ct.ThrowIfCancellationRequested();
    }, ct);

    src.Cancel();
    try
    {
        t.Wait();
    }
    catch (AggregateException e)
    {
        // Don't actually use an empty catch clause, this is
        // for the sake of demonstration.
    }

    Console.WriteLine("Canceled: {0} . Finished: {1} . Error: {2}",
                       t.IsCanceled, t.IsCompleted, t.IsFaulted);
}
person Yuval Itzchakov    schedule 24.02.2016