Unity Awaitables - Catching 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.