Use of IsCancellationRequested property?

2019-07-31 19:41发布

问题:

What is the use of CancellationToken's IsCancellationRequested property? Consider below code

static void Main(string[] args)
{
    CancellationTokenSource tokenSource = new CancellationTokenSource();
    var token = tokenSource.Token;
    Console.WriteLine("Press Enter to Start.\nAgain Press enter to finish.");
    Console.ReadLine();
    Task t = new Task(() =>
    {
        int i = 0;
        while (true)
        {
            if (token.IsCancellationRequested)
            {
                Console.WriteLine("Task Cancel requested");
                break;
            }
            Console.WriteLine(i++);
        }
    }, token);

    t.Start();

    // wait for input before exiting
    Console.ReadLine();
    tokenSource.Cancel();
    if(t.Status==TaskStatus.Canceled)
        Console.WriteLine("Task was cancelled");
    else
        Console.WriteLine("Task completed");
}

I find that on rare occasions code inside if block doesn't run. If so what is the use of polling to see if cancellation is requested?

回答1:

The problem with your code is that you don't wait for the Task to finish. So, what can happen is this:

  1. You call Cancel().
  2. You check Status, which returns Running.
  3. Confusingly, you write “Task completed” when the Task is still running.
  4. Main() completes, application exits.
  5. (At this point, IsCancellationRequested would be checked from the background thread. But that never happens, since the application already exited.)

To fix that, add t.Wait() after you call Cancel().

But that still won't fix your program completely. You need to tell the Task that it was canceled. And you do that by throwing OperationCanceledException that contains the CancellationToken (the usual way to do that is to call ThrowIfCancellationRequested()).

One issue with that is that Wait()ing on a Task that was canceled will throw an exception, so you will have to catch that.