public static async UniTask <T> Timeout <T>(this UniTask <T> task, TimeSpan timeout, bool ignoreTimeScale = true, PlayerLoopTiming timeoutCheckTiming = PlayerLoopTiming.Update, CancellationTokenSource taskCancellationTokenSource = null) { // left, right both suppress operation canceled exception. var delayCancellationTokenSource = new CancellationTokenSource(); var timeoutTask = (UniTask)UniTask.Delay(timeout, ignoreTimeScale, timeoutCheckTiming).SuppressCancellationThrow(); var(hasValue, value) = await UniTask.WhenAny(task.SuppressCancellationThrow(), timeoutTask); if (!hasValue) { if (taskCancellationTokenSource != null) { taskCancellationTokenSource.Cancel(); taskCancellationTokenSource.Dispose(); } throw new TimeoutException("Exceed Timeout:" + timeout); } delayCancellationTokenSource.Cancel(); delayCancellationTokenSource.Dispose(); if (value.IsCanceled) { Error.ThrowOperationCanceledException(); } return(value.Result); }
static async UniTaskVoid CancelAfterCore(CancellationTokenSource cts, UniTask delayTask) { var alreadyCanceled = await delayTask.SuppressCancellationThrow(); if (!alreadyCanceled) { cts.Cancel(); cts.Dispose(); } }