Pages

Monday, 21 December 2015

In my previous post, "How to cancel a Task", I mentioned that MSDN recommends throwing OperationCanceledException from a cancelled task. But the following example shows that canceling .NET methods makes them throw a different exception type - TaskCanceledException:

So why .NET does not follow its own rules? Why exception thrown in the example above was not OperationCanceledException?

I asked this question on SO and this is how I interpret the answer I got:

(1) System.OperationCanceledException class has been around longer than TPL. MSDN describes it as: "The exception that is thrown in a thread upon cancellation of an operation that the thread was executing." It is intended to be thrown from a thread in which operation is executed. .NET async API are actually synchronous operations (return Task, not marked as async). They don't have additional thread involved which makes OperationCanceledException not appropriate exception to be thrown.

(2) It is different to cancel a Task (setup of the engine which will execute "real work", user's operation) than to cancel operation itself. For example, we can pass already cancelled token to a task or can simply create already cancelled task. Operation and its thread are not started at all in these cases but if we await such task and catch OperationCanceledException we might think they were actually started. So it makes sense to use different type of the exception in these two different scenarios.

From the points made above we can conclude that caller of the cancelable task can expect two types of exceptions:OperationCanceledException and TaskCanceledException. As the latter derives from the former, it is enough to handle OperationCanceledException if we want to handle the case of canceled task: