C # async CTP - How to mark an async task as canceled without throwing a TaskCanceledException?

I have a short async task that often needs to be canceled after it starts. The Task class has an IsCanceled indicator, which, in my opinion, will be convenient to use to indicate that the async task was canceled without completion before completion, but as far as I can tell, the only way for the async task to be marked as canceled is for TaskCanceledException exceptions in an async function. Usually throwing an exception to indicate a situation that occurs in exceptional cases goes against the way I understand that exceptions should be used. Does anyone know a better way to indicate that an asynchronous task should be canceled when it is expected to happen often?

My next best alternative is to return a structure that has its own IsCanceled property:

(I ignored some good coding and style methods for brevity here)

class MightBeCanceled<T> { public readonly T Value; public readonly bool IsCanceled; public MightBeCanceled(T value) { Value = value; IsCanceled = false; } public static MightBeCanceled<T> Canceled = new MightBeCanceled<T>(default(T), true); private MightBeCanceled(T value, bool isCanceled) { Value = value; IsCanceled = isCanceled; } } ... static async Task<MightBeCanceled<int>> Foo() { if (someCancellationCondition) return MightBeCanceled<int>.Canceled; else return new MightBeCanceled<int>(42); } static async void Bar() { var mightBeCanceled = await Foo(); if (mightBeCanceled.IsCanceled) ; // Take canceled action else ; // Take normal action } 

But it seems redundant and difficult to use. Not to mention that it introduces consistency issues because there will be two IsCanceled (one in Task and one in MightBeCanceled).

+6
source share
2 answers

The problem is that the exception will be invisible until you decide to wait. Thus, the action of the await call means that you will eventually observe the exception at some point when the final value is returned, or if you wait for the task to complete. However, if you don't care (it's a fire task and forget it), then exception is not a problem (for the most part).

I also find this a bit strange, you always need to try / catch the task to handle generalized exceptions. However, think about this a bit:

  try { var myResult = await Foo(); // Do Success Actions Here... } catch(AggregateException e) { e.Flatten().Handle(ex => { if(ex is OperationCanceledException) { // Do Canceled Thing Here return true; } return false; }); } 

It is not too far. In many ways I think about canceling another task and how can I do this? ThreadAbortException ? It seems until has been done to just throw a specific exception on cancellation.

This is pretty much a pattern that I've seen in several places, in order to handle cancellation.

+2
source

Typically, the goal of a revocation is for an invoker of an asynchronous action to say that the action should stop processing. To do this, you pass the CancellationToken to the asynchronous method. This is why waiting for the task that sets IsCancelled throws itself. This meant an exceptional signal to an externally triggered action. A task cancellation should not be used for the control flow, but only in order to give the asynchronous action the opportunity to complete the work earlier if the waiting party reports that it no longer wants the result.

If you break asynchronous actions inside, you already overloaded the concept, and I would say that this reflects the fact that the difference in cancellation is and should be the property on the results container, similar to how you proposed it. But instead of calling it MightBeCancelled<T> , perhaps something like InternallyCancellableResult<T> to reflect the difference in cancellation concepts.

+2
source

Source: https://habr.com/ru/post/894877/


All Articles