diff --git a/src/UniTask/Assets/Plugins/UniTask/Runtime/UniTask.Factory.cs b/src/UniTask/Assets/Plugins/UniTask/Runtime/UniTask.Factory.cs index c56cb03..2f6a6a9 100644 --- a/src/UniTask/Assets/Plugins/UniTask/Runtime/UniTask.Factory.cs +++ b/src/UniTask/Assets/Plugins/UniTask/Runtime/UniTask.Factory.cs @@ -194,6 +194,7 @@ namespace Cysharp.Threading.Tasks sealed class ExceptionResultSource : IUniTaskSource { readonly ExceptionDispatchInfo exception; + bool calledGet; public ExceptionResultSource(Exception exception) { @@ -202,6 +203,11 @@ namespace Cysharp.Threading.Tasks public void GetResult(short token) { + if (!calledGet) + { + calledGet = true; + GC.SuppressFinalize(this); + } exception.Throw(); } @@ -219,11 +225,20 @@ namespace Cysharp.Threading.Tasks { continuation(state); } + + ~ExceptionResultSource() + { + if (!calledGet) + { + UniTaskScheduler.PublishUnobservedTaskException(exception.SourceException); + } + } } sealed class ExceptionResultSource : IUniTaskSource { readonly ExceptionDispatchInfo exception; + bool calledGet; public ExceptionResultSource(Exception exception) { @@ -232,12 +247,22 @@ namespace Cysharp.Threading.Tasks public T GetResult(short token) { + if (!calledGet) + { + calledGet = true; + GC.SuppressFinalize(this); + } exception.Throw(); return default; } void IUniTaskSource.GetResult(short token) { + if (!calledGet) + { + calledGet = true; + GC.SuppressFinalize(this); + } exception.Throw(); } @@ -255,6 +280,14 @@ namespace Cysharp.Threading.Tasks { continuation(state); } + + ~ExceptionResultSource() + { + if (!calledGet) + { + UniTaskScheduler.PublishUnobservedTaskException(exception.SourceException); + } + } } sealed class CanceledResultSource : IUniTaskSource diff --git a/src/UniTask/Assets/Tests/AsyncTest.cs b/src/UniTask/Assets/Tests/AsyncTest.cs index c329dbf..75eec2c 100644 --- a/src/UniTask/Assets/Tests/AsyncTest.cs +++ b/src/UniTask/Assets/Tests/AsyncTest.cs @@ -366,6 +366,28 @@ namespace Cysharp.Threading.TasksTests UniTaskScheduler.UnobservedTaskException -= action; }); + [UnityTest] + public IEnumerator ThrowExceptionUnawaited() => UniTask.ToCoroutine(async () => + { + LogAssert.Expect(LogType.Exception, "Exception: MyException"); + +#pragma warning disable 1998 + async UniTask Throw() => throw new Exception("MyException"); +#pragma warning restore 1998 + +#pragma warning disable 4014 + Throw(); +#pragma warning restore 4014 + + await UniTask.DelayFrame(3); + + GC.Collect(); + GC.WaitForPendingFinalizers(); + GC.Collect(); + + await UniTask.DelayFrame(1); + }); + async UniTask InException1() { await UniTask.Yield();