Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using CancellationToken for timeout in Task.Run does not work [duplicate]

OK, my questions is really simple. Why this code does not throw TaskCancelledException?

static void Main() {     var v = Task.Run(() =>     {         Thread.Sleep(1000);         return 10;     }, new CancellationTokenSource(500).Token).Result;      Console.WriteLine(v); // this outputs 10 - instead of throwing error.     Console.Read(); } 

But this one works

static void Main() {     var v = Task.Run(() =>     {         Thread.Sleep(1000);         return 10;     }, new CancellationToken(true).Token).Result;      Console.WriteLine(v); // this one throws     Console.Read(); } 
like image 477
Aliostad Avatar asked Mar 25 '14 14:03

Aliostad


People also ask

Which method can you use to cancel an ongoing operation that uses CancellationToken?

The CancellationToken is used in asynchronous task. The CancellationTokenSource token is used to signal that the Task should cancel itself. In the above case, the operation will just end when cancellation is requested via Cancel() method.

What is the purpose of CancellationToken?

A CancellationToken enables cooperative cancellation between threads, thread pool work items, or Task objects. You create a cancellation token by instantiating a CancellationTokenSource object, which manages cancellation tokens retrieved from its CancellationTokenSource. Token property.

Can I reuse CancellationTokenSource?

CancellationTokenSource is quite a heavyweight object and its not normally cancelled; however it can't be pooled or reused because its registrations cannot be cleared.

Which of the following option should be used to implement cancellation for a long running task?

In this article, we will learn How to cancel or interrupt the Long Running Task using a Cancellationtokensource method in . NET 4.0. In this article, we are going to learn how to cancel or interrupt the Long Running Task using the Cancellationtokensource method in .


2 Answers

Cancellation in Managed Threads:

Cancellation is cooperative and is not forced on the listener. The listener determines how to gracefully terminate in response to a cancellation request.

You didn't write any code inside your Task.Run method to access your CancellationToken and to implement cancellation - so you effectively ignored the request for cancellation and ran to completion.

like image 136
Damien_The_Unbeliever Avatar answered Sep 20 '22 06:09

Damien_The_Unbeliever


There is a difference in canceling a running task, and a task scheduled to run.

After the call to the Task.Run method, the task is only scheduled, and probably have not been executed yet.

When you use the Task.Run(..., CancellationToken) family of overloads with cancellation support, the cancellation token is checked when the task is about to run. If the cancellation token has IsCancellationRequested set to true at this time, an exception of the type TaskCanceledException is thrown.

If the task is already running, it is the task's responsibility to call the ThrowIfCancellationRequested method, or just throw the OperationCanceledException.

According to MSDN, it's just a convenience method for the following:

if (token.IsCancellationRequested) throw new OperationCanceledException(token);

Note the different kind of exception used in this two cases:

catch (TaskCanceledException ex) {     // Task was canceled before running. } catch (OperationCanceledException ex) {     // Task was canceled while running. } 

Also note that TaskCanceledException derives from OperationCanceledException, so you can just have one catch clause for the OperationCanceledException type:

catch (OperationCanceledException ex) {     if (ex is TaskCanceledException)         // Task was canceled before running.     // Task was canceled while running. } 
like image 27
George Polevoy Avatar answered Sep 21 '22 06:09

George Polevoy