Awaitables should not throw exceptions by default

The problem:
Currently Awaitables throw exceptions when they are cancelled.

This requires us to catch exceptions in order to cancel Awaitables which is a common thing to do in async workflows. This has performance drawbacks because exception handling is expensive and makes Awaitables less viable as a result.

The current solution:
In this thread it was said that the reason Awaitables throw by default is because:

Quote from ** @simon-ferquel-unity **
“”"
The problem with not raising the exception, is that it is totally unsafe, as the continuation will never run.
Imagine something like the following:

Code (CSharp):

  • using(var someNativeResource = SomeApi.ReturningSomethingThatNeedsDispose()){
  • await SomeAwaitableThatCanBeJustInterupted();
  • }
    • // or even worse with standard-ish use of SemaphoreSlim:
    • await semaphoreSlim.WaitAsync();
  • try{
  • await SomeNonExceptionCancellableAsync();
  • }
  • finally{
  • semaphoreSlim.Release();
  • }

In the first case, Dispose won’t ever be called, which can be problematic in some scenarios.
Second case, you will end up with a deadlock as the semaphore won’t be released.
“”"

The proposed solution:
The solution to this is an opt-in solution just like C# Tasks do
CancellationToken.ThrowIfCancellationRequested

This lets you throw exceptions in the edge cases where it’s necessary, but comes without the performance drawbacks of catching exceptions where it’s not needed and simple CancellationToken.IsCancellationRequested checks will suffice.

5 Likes

Absolutely agree.

And please add a onDisabledCancellationToken to Mono behaviour, not everyone wants to destroy their UI scene when a user clicks cancel on a download progress bar…

2 Likes