Unity Awaitables - Catching swallowed exceptions
How to catch Awaitable swallowed exceptions.
If you're working with Awaitables in Unity, you may stumped upon the fact that if you run an Awaitable without awaiting, all exceptions are swallowed, e.g.:
private async Awaitable DoSomething()
{
// your code.
}
private void Start()
{
_ = DoSomething();
}
This is a typical pattern for starting asynchronous work without waiting for the result. In this case, if DoSomething
throws, the exception will be swallowed silently. This is not a unique Unity behavior but how Tasks in C# work.
Now, if you want to get the swallowed exceptions, you can use this extension method:
public static class AwaitableExtensions
{
public static void Forget(this Awaitable awaitable)
{
var awaiter = awaitable.GetAwaiter();
if (awaitable.IsCompleted)
{
try
{
awaiter.GetResult();
}
catch (Exception ex) when (ex is OperationCanceledException)
{
// Silently swallow OperationCanceledExceptions since this is expected.
// Everything else will throw.
}
}
else
{
awaiter.OnCompleted(() =>
{
try
{
awaiter.GetResult();
}
catch (Exception ex) when (ex is OperationCanceledException)
{
// Silently swallow OperationCanceledExceptions since this is expected.
// Everything else will throw.
}
});
}
}
}
And then call your Awaitable like this:
private void Start()
{
DoSomething().Forget();
}
Now, any error will show up in the console as usual.
If you're using UniTask
, you also want to use its Forget()
method when you're not going to await
a UniTask
which basically is doing the same to catch any exception.