Canceling a task

2019-02-12 12:47发布

问题:

I have a task which i need to cancel if the wait time is over. For instance

var t = Task.Factory.StartNew(() => 
{
  Thread.Sleep(5000) // some long running task
  "do something"
});
Task.WaitAll(new[] {t}, 1000);

But it seems the task still keeps working. I tried using CancellationTokenSource but that didnt seem to work as well.

I confirmed this using the following snippet

static void Main(string[] args)
        {
            var cancellationTokenSource = new CancellationTokenSource();

            var t = Task.Factory.StartNew(() => {
                Thread.Sleep(5000);
                Console.WriteLine("Still working");
            }, cancellationTokenSource.Token);

            Task.WaitAll(new[] {t}, 1000);

            cancellationTokenSource.Cancel();

            Console.ReadLine();
        }

Console displays "Still working". I thought the task would have been cancelled.

I am sure I am missing something. What am i missing? Thanks.

回答1:

Cancellation tokens don't magically cancel anything. They just allow you to check for cancellation in a standardized way, e.g. via ThrowIfCancellationRequested.

So typically you'd have some task which needs to perform a lot of work. It periodically calls ThrowIfCancellationRequested, and then any code which needs to cancel the task will call Cancel on the CancellationTokenSource when it needs to. The task will throw when it next checks for cancellation, and all will be well.

It sounds like you're looking for a non-cooperative cancellation - and that would be dangerous, for exactly the same reasons that the normal Thread.Abort is dangerous. It's cleaner to let the task pick the points at which it will allow itself to be cancelled.