1

In the following piece of code I have a task that gets canceled when the user presses any key. When doing so the ContinuationTask is invoked stating that the task was canceled. The ContinuationTask is configured so that it only runs when a task was canceled - and it actually does.

But when I check for the status of the task after completion in the calling thread, I get back "RanToCompletion". How is that possible?

Here is the code:

private static void ContinuationForCanceledTask()
{
    CancellationTokenSource tokenSource = new CancellationTokenSource();

    CancellationToken token = tokenSource.Token;

    Task t = Task.Run(
        () =>
        {
            while (!token.IsCancellationRequested)
            {
                Console.WriteLine("Nelson: Haha! - I am still running!!");

                Thread.Sleep(1000);
            }

            token.ThrowIfCancellationRequested();
        }, token);

    //This continuation task is invoked as expected
    t.ContinueWith(
        (tawsk) =>
        {
            Console.WriteLine("Tawsk was canceled");
        }
        , TaskContinuationOptions.OnlyOnCanceled);

    Console.WriteLine("Press any key to stop Nelson from laughing at you...");

    Console.ReadKey();

    tokenSource.Cancel();

    t.Wait();

    //Returns "RanToCompletion"
    Console.WriteLine("State of the Task is {0}", t.Status);
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
FunkyPeanut
  • 1,152
  • 2
  • 9
  • 28
  • 1
    you should add a `try-catch` at `t.Wait();` or your program ends with exception unhandled. – kennyzx Dec 24 '14 at 05:08
  • 1
    Can you please check that this reproduce each time ? Second thing please check that token.ThrowIfCancellationRequested() is hit or not. – dotnetstep Dec 24 '14 at 05:10
  • Looks like the call to `ThrowIfCancellationRequested()` is outside the loop, and won't get hit until after the task finished its main duties. – Nathan Tuggy Dec 24 '14 at 05:47
  • @NathanTuggy there is no such thing as _main duties_ of a task, the task ran to completion if neither an exception nor a cancellation ever raised, and the task's status is set after the cancellation is raised, not after the _main duties_, if by which you mean the while loop. – kennyzx Dec 24 '14 at 08:07
  • @kennyzx: hmm, no, you're right, that while condition should be good enough. The more puzzling. – Nathan Tuggy Dec 24 '14 at 08:12
  • @kennyzx Thanks for that. Actually I got my approach above from a book stating "instead of catching the exception you could add a continuation task...". And even adding a try catch block would not change the output. It is now that I realize that I only get a state of Canceled when I remove the continuation and add a try-catch block. (Only removing the block (of course) results in an Aggregate Exception). May it be possible that "RanToCompletion" refers to the continuation having run to completion? Would make sense since I was already informed about the cancellation in the continuation-block. – FunkyPeanut Dec 24 '14 at 11:59
  • @dotnetstep Yes it is reproduceable and the call is certainly made every time. – FunkyPeanut Dec 24 '14 at 12:00
  • @kennyzx What supports my theory from above is that my code throws a TaskCancellationException when I change the TaskContinuationOptions to "OnNotCancelled". It works though when setting it to "NotOnRanToCompletion". – FunkyPeanut Dec 24 '14 at 12:06
  • 2
    I can't repro. Every time it prints "State of the Task is Canceled" (catching the AggregateException), I tried both v4.5/v4.5.1 (there should be no difference), can't guess why it can happen :( – kennyzx Dec 24 '14 at 15:13
  • Just as I expected, I am unable to reproduce the wrong behavior either. I get the exception thrown, and the task status is `Canceled`. Obviously the code you posted in your question is either not really the code you're running, or there is some other code in your whole program that you've neglected to share with us and which is causing the problem. Post a good code example if you want help. – Peter Duniho Dec 24 '14 at 18:31
  • @Peter Duniho You are right. I am not quite sure how I could mess this up and what messed this up since my last saved version is gone... I am sorry and still thanks for you help. – FunkyPeanut Dec 25 '14 at 14:56
  • Necro, but perhaps it was an `async void` situation? Good explanation [here](https://stackoverflow.com/a/23936656/152997). – McGuireV10 Feb 03 '19 at 17:12

0 Answers0