mirror of
https://github.com/Alex-Rachel/TEngine.git
synced 2025-08-14 16:51:28 +00:00
Init TEngine4.0.0
Init TEngine4.0.0
This commit is contained in:
921
UnityProject/Packages/UniTask/Runtime/UniTaskExtensions.cs
Normal file
921
UnityProject/Packages/UniTask/Runtime/UniTaskExtensions.cs
Normal file
@@ -0,0 +1,921 @@
|
||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Cysharp.Threading.Tasks.Internal;
|
||||
|
||||
namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
public static partial class UniTaskExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Convert Task[T] -> UniTask[T].
|
||||
/// </summary>
|
||||
public static UniTask<T> AsUniTask<T>(this Task<T> task, bool useCurrentSynchronizationContext = true)
|
||||
{
|
||||
var promise = new UniTaskCompletionSource<T>();
|
||||
|
||||
task.ContinueWith((x, state) =>
|
||||
{
|
||||
var p = (UniTaskCompletionSource<T>)state;
|
||||
|
||||
switch (x.Status)
|
||||
{
|
||||
case TaskStatus.Canceled:
|
||||
p.TrySetCanceled();
|
||||
break;
|
||||
case TaskStatus.Faulted:
|
||||
p.TrySetException(x.Exception.InnerException ?? x.Exception);
|
||||
break;
|
||||
case TaskStatus.RanToCompletion:
|
||||
p.TrySetResult(x.Result);
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}, promise, useCurrentSynchronizationContext ? TaskScheduler.FromCurrentSynchronizationContext() : TaskScheduler.Current);
|
||||
|
||||
return promise.Task;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert Task -> UniTask.
|
||||
/// </summary>
|
||||
public static UniTask AsUniTask(this Task task, bool useCurrentSynchronizationContext = true)
|
||||
{
|
||||
var promise = new UniTaskCompletionSource();
|
||||
|
||||
task.ContinueWith((x, state) =>
|
||||
{
|
||||
var p = (UniTaskCompletionSource)state;
|
||||
|
||||
switch (x.Status)
|
||||
{
|
||||
case TaskStatus.Canceled:
|
||||
p.TrySetCanceled();
|
||||
break;
|
||||
case TaskStatus.Faulted:
|
||||
p.TrySetException(x.Exception.InnerException ?? x.Exception);
|
||||
break;
|
||||
case TaskStatus.RanToCompletion:
|
||||
p.TrySetResult();
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}, promise, useCurrentSynchronizationContext ? TaskScheduler.FromCurrentSynchronizationContext() : TaskScheduler.Current);
|
||||
|
||||
return promise.Task;
|
||||
}
|
||||
|
||||
public static Task<T> AsTask<T>(this UniTask<T> task)
|
||||
{
|
||||
try
|
||||
{
|
||||
UniTask<T>.Awaiter awaiter;
|
||||
try
|
||||
{
|
||||
awaiter = task.GetAwaiter();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Task.FromException<T>(ex);
|
||||
}
|
||||
|
||||
if (awaiter.IsCompleted)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = awaiter.GetResult();
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Task.FromException<T>(ex);
|
||||
}
|
||||
}
|
||||
|
||||
var tcs = new TaskCompletionSource<T>();
|
||||
|
||||
awaiter.SourceOnCompleted(state =>
|
||||
{
|
||||
using (var tuple = (StateTuple<TaskCompletionSource<T>, UniTask<T>.Awaiter>)state)
|
||||
{
|
||||
var (inTcs, inAwaiter) = tuple;
|
||||
try
|
||||
{
|
||||
var result = inAwaiter.GetResult();
|
||||
inTcs.SetResult(result);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
inTcs.SetException(ex);
|
||||
}
|
||||
}
|
||||
}, StateTuple.Create(tcs, awaiter));
|
||||
|
||||
return tcs.Task;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Task.FromException<T>(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static Task AsTask(this UniTask task)
|
||||
{
|
||||
try
|
||||
{
|
||||
UniTask.Awaiter awaiter;
|
||||
try
|
||||
{
|
||||
awaiter = task.GetAwaiter();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Task.FromException(ex);
|
||||
}
|
||||
|
||||
if (awaiter.IsCompleted)
|
||||
{
|
||||
try
|
||||
{
|
||||
awaiter.GetResult(); // check token valid on Succeeded
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Task.FromException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
var tcs = new TaskCompletionSource<object>();
|
||||
|
||||
awaiter.SourceOnCompleted(state =>
|
||||
{
|
||||
using (var tuple = (StateTuple<TaskCompletionSource<object>, UniTask.Awaiter>)state)
|
||||
{
|
||||
var (inTcs, inAwaiter) = tuple;
|
||||
try
|
||||
{
|
||||
inAwaiter.GetResult();
|
||||
inTcs.SetResult(null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
inTcs.SetException(ex);
|
||||
}
|
||||
}
|
||||
}, StateTuple.Create(tcs, awaiter));
|
||||
|
||||
return tcs.Task;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Task.FromException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static AsyncLazy ToAsyncLazy(this UniTask task)
|
||||
{
|
||||
return new AsyncLazy(task);
|
||||
}
|
||||
|
||||
public static AsyncLazy<T> ToAsyncLazy<T>(this UniTask<T> task)
|
||||
{
|
||||
return new AsyncLazy<T>(task);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ignore task result when cancel raised first.
|
||||
/// </summary>
|
||||
public static UniTask AttachExternalCancellation(this UniTask task, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!cancellationToken.CanBeCanceled)
|
||||
{
|
||||
return task;
|
||||
}
|
||||
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
return UniTask.FromCanceled(cancellationToken);
|
||||
}
|
||||
|
||||
if (task.Status.IsCompleted())
|
||||
{
|
||||
return task;
|
||||
}
|
||||
|
||||
return new UniTask(new AttachExternalCancellationSource(task, cancellationToken), 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ignore task result when cancel raised first.
|
||||
/// </summary>
|
||||
public static UniTask<T> AttachExternalCancellation<T>(this UniTask<T> task, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!cancellationToken.CanBeCanceled)
|
||||
{
|
||||
return task;
|
||||
}
|
||||
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
return UniTask.FromCanceled<T>(cancellationToken);
|
||||
}
|
||||
|
||||
if (task.Status.IsCompleted())
|
||||
{
|
||||
return task;
|
||||
}
|
||||
|
||||
return new UniTask<T>(new AttachExternalCancellationSource<T>(task, cancellationToken), 0);
|
||||
}
|
||||
|
||||
sealed class AttachExternalCancellationSource : IUniTaskSource
|
||||
{
|
||||
static readonly Action<object> cancellationCallbackDelegate = CancellationCallback;
|
||||
|
||||
CancellationToken cancellationToken;
|
||||
CancellationTokenRegistration tokenRegistration;
|
||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||
|
||||
public AttachExternalCancellationSource(UniTask task, CancellationToken cancellationToken)
|
||||
{
|
||||
this.cancellationToken = cancellationToken;
|
||||
this.tokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallbackDelegate, this);
|
||||
RunTask(task).Forget();
|
||||
}
|
||||
|
||||
async UniTaskVoid RunTask(UniTask task)
|
||||
{
|
||||
try
|
||||
{
|
||||
await task;
|
||||
core.TrySetResult(AsyncUnit.Default);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
core.TrySetException(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
tokenRegistration.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
static void CancellationCallback(object state)
|
||||
{
|
||||
var self = (AttachExternalCancellationSource)state;
|
||||
self.core.TrySetCanceled(self.cancellationToken);
|
||||
}
|
||||
|
||||
public void GetResult(short token)
|
||||
{
|
||||
core.GetResult(token);
|
||||
}
|
||||
|
||||
public UniTaskStatus GetStatus(short token)
|
||||
{
|
||||
return core.GetStatus(token);
|
||||
}
|
||||
|
||||
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||
{
|
||||
core.OnCompleted(continuation, state, token);
|
||||
}
|
||||
|
||||
public UniTaskStatus UnsafeGetStatus()
|
||||
{
|
||||
return core.UnsafeGetStatus();
|
||||
}
|
||||
}
|
||||
|
||||
sealed class AttachExternalCancellationSource<T> : IUniTaskSource<T>
|
||||
{
|
||||
static readonly Action<object> cancellationCallbackDelegate = CancellationCallback;
|
||||
|
||||
CancellationToken cancellationToken;
|
||||
CancellationTokenRegistration tokenRegistration;
|
||||
UniTaskCompletionSourceCore<T> core;
|
||||
|
||||
public AttachExternalCancellationSource(UniTask<T> task, CancellationToken cancellationToken)
|
||||
{
|
||||
this.cancellationToken = cancellationToken;
|
||||
this.tokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallbackDelegate, this);
|
||||
RunTask(task).Forget();
|
||||
}
|
||||
|
||||
async UniTaskVoid RunTask(UniTask<T> task)
|
||||
{
|
||||
try
|
||||
{
|
||||
core.TrySetResult(await task);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
core.TrySetException(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
tokenRegistration.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
static void CancellationCallback(object state)
|
||||
{
|
||||
var self = (AttachExternalCancellationSource<T>)state;
|
||||
self.core.TrySetCanceled(self.cancellationToken);
|
||||
}
|
||||
|
||||
void IUniTaskSource.GetResult(short token)
|
||||
{
|
||||
core.GetResult(token);
|
||||
}
|
||||
|
||||
public T GetResult(short token)
|
||||
{
|
||||
return core.GetResult(token);
|
||||
}
|
||||
|
||||
public UniTaskStatus GetStatus(short token)
|
||||
{
|
||||
return core.GetStatus(token);
|
||||
}
|
||||
|
||||
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||
{
|
||||
core.OnCompleted(continuation, state, token);
|
||||
}
|
||||
|
||||
public UniTaskStatus UnsafeGetStatus()
|
||||
{
|
||||
return core.UnsafeGetStatus();
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
|
||||
public static IEnumerator ToCoroutine<T>(this UniTask<T> task, Action<T> resultHandler = null, Action<Exception> exceptionHandler = null)
|
||||
{
|
||||
return new ToCoroutineEnumerator<T>(task, resultHandler, exceptionHandler);
|
||||
}
|
||||
|
||||
public static IEnumerator ToCoroutine(this UniTask task, Action<Exception> exceptionHandler = null)
|
||||
{
|
||||
return new ToCoroutineEnumerator(task, exceptionHandler);
|
||||
}
|
||||
|
||||
public static async UniTask Timeout(this UniTask task, TimeSpan timeout, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming timeoutCheckTiming = PlayerLoopTiming.Update, CancellationTokenSource taskCancellationTokenSource = null)
|
||||
{
|
||||
var delayCancellationTokenSource = new CancellationTokenSource();
|
||||
var timeoutTask = UniTask.Delay(timeout, delayType, timeoutCheckTiming, delayCancellationTokenSource.Token).SuppressCancellationThrow();
|
||||
|
||||
int winArgIndex;
|
||||
bool taskResultIsCanceled;
|
||||
try
|
||||
{
|
||||
(winArgIndex, taskResultIsCanceled, _) = await UniTask.WhenAny(task.SuppressCancellationThrow(), timeoutTask);
|
||||
}
|
||||
catch
|
||||
{
|
||||
delayCancellationTokenSource.Cancel();
|
||||
delayCancellationTokenSource.Dispose();
|
||||
throw;
|
||||
}
|
||||
|
||||
// timeout
|
||||
if (winArgIndex == 1)
|
||||
{
|
||||
if (taskCancellationTokenSource != null)
|
||||
{
|
||||
taskCancellationTokenSource.Cancel();
|
||||
taskCancellationTokenSource.Dispose();
|
||||
}
|
||||
|
||||
throw new TimeoutException("Exceed Timeout:" + timeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
delayCancellationTokenSource.Cancel();
|
||||
delayCancellationTokenSource.Dispose();
|
||||
}
|
||||
|
||||
if (taskResultIsCanceled)
|
||||
{
|
||||
Error.ThrowOperationCanceledException();
|
||||
}
|
||||
}
|
||||
|
||||
public static async UniTask<T> Timeout<T>(this UniTask<T> task, TimeSpan timeout, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming timeoutCheckTiming = PlayerLoopTiming.Update, CancellationTokenSource taskCancellationTokenSource = null)
|
||||
{
|
||||
var delayCancellationTokenSource = new CancellationTokenSource();
|
||||
var timeoutTask = UniTask.Delay(timeout, delayType, timeoutCheckTiming, delayCancellationTokenSource.Token).SuppressCancellationThrow();
|
||||
|
||||
int winArgIndex;
|
||||
(bool IsCanceled, T Result) taskResult;
|
||||
try
|
||||
{
|
||||
(winArgIndex, taskResult, _) = await UniTask.WhenAny(task.SuppressCancellationThrow(), timeoutTask);
|
||||
}
|
||||
catch
|
||||
{
|
||||
delayCancellationTokenSource.Cancel();
|
||||
delayCancellationTokenSource.Dispose();
|
||||
throw;
|
||||
}
|
||||
|
||||
// timeout
|
||||
if (winArgIndex == 1)
|
||||
{
|
||||
if (taskCancellationTokenSource != null)
|
||||
{
|
||||
taskCancellationTokenSource.Cancel();
|
||||
taskCancellationTokenSource.Dispose();
|
||||
}
|
||||
|
||||
throw new TimeoutException("Exceed Timeout:" + timeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
delayCancellationTokenSource.Cancel();
|
||||
delayCancellationTokenSource.Dispose();
|
||||
}
|
||||
|
||||
if (taskResult.IsCanceled)
|
||||
{
|
||||
Error.ThrowOperationCanceledException();
|
||||
}
|
||||
|
||||
return taskResult.Result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Timeout with suppress OperationCanceledException. Returns (bool, IsCacneled).
|
||||
/// </summary>
|
||||
public static async UniTask<bool> TimeoutWithoutException(this UniTask task, TimeSpan timeout, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming timeoutCheckTiming = PlayerLoopTiming.Update, CancellationTokenSource taskCancellationTokenSource = null)
|
||||
{
|
||||
var delayCancellationTokenSource = new CancellationTokenSource();
|
||||
var timeoutTask = UniTask.Delay(timeout, delayType, timeoutCheckTiming, delayCancellationTokenSource.Token).SuppressCancellationThrow();
|
||||
|
||||
int winArgIndex;
|
||||
bool taskResultIsCanceled;
|
||||
try
|
||||
{
|
||||
(winArgIndex, taskResultIsCanceled, _) = await UniTask.WhenAny(task.SuppressCancellationThrow(), timeoutTask);
|
||||
}
|
||||
catch
|
||||
{
|
||||
delayCancellationTokenSource.Cancel();
|
||||
delayCancellationTokenSource.Dispose();
|
||||
return true;
|
||||
}
|
||||
|
||||
// timeout
|
||||
if (winArgIndex == 1)
|
||||
{
|
||||
if (taskCancellationTokenSource != null)
|
||||
{
|
||||
taskCancellationTokenSource.Cancel();
|
||||
taskCancellationTokenSource.Dispose();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
delayCancellationTokenSource.Cancel();
|
||||
delayCancellationTokenSource.Dispose();
|
||||
}
|
||||
|
||||
if (taskResultIsCanceled)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Timeout with suppress OperationCanceledException. Returns (bool IsTimeout, T Result).
|
||||
/// </summary>
|
||||
public static async UniTask<(bool IsTimeout, T Result)> TimeoutWithoutException<T>(this UniTask<T> task, TimeSpan timeout, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming timeoutCheckTiming = PlayerLoopTiming.Update, CancellationTokenSource taskCancellationTokenSource = null)
|
||||
{
|
||||
var delayCancellationTokenSource = new CancellationTokenSource();
|
||||
var timeoutTask = UniTask.Delay(timeout, delayType, timeoutCheckTiming, delayCancellationTokenSource.Token).SuppressCancellationThrow();
|
||||
|
||||
int winArgIndex;
|
||||
(bool IsCanceled, T Result) taskResult;
|
||||
try
|
||||
{
|
||||
(winArgIndex, taskResult, _) = await UniTask.WhenAny(task.SuppressCancellationThrow(), timeoutTask);
|
||||
}
|
||||
catch
|
||||
{
|
||||
delayCancellationTokenSource.Cancel();
|
||||
delayCancellationTokenSource.Dispose();
|
||||
return (true, default);
|
||||
}
|
||||
|
||||
// timeout
|
||||
if (winArgIndex == 1)
|
||||
{
|
||||
if (taskCancellationTokenSource != null)
|
||||
{
|
||||
taskCancellationTokenSource.Cancel();
|
||||
taskCancellationTokenSource.Dispose();
|
||||
}
|
||||
|
||||
return (true, default);
|
||||
}
|
||||
else
|
||||
{
|
||||
delayCancellationTokenSource.Cancel();
|
||||
delayCancellationTokenSource.Dispose();
|
||||
}
|
||||
|
||||
if (taskResult.IsCanceled)
|
||||
{
|
||||
return (true, default);
|
||||
}
|
||||
|
||||
return (false, taskResult.Result);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
public static void Forget(this UniTask task)
|
||||
{
|
||||
var awaiter = task.GetAwaiter();
|
||||
if (awaiter.IsCompleted)
|
||||
{
|
||||
try
|
||||
{
|
||||
awaiter.GetResult();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
awaiter.SourceOnCompleted(state =>
|
||||
{
|
||||
using (var t = (StateTuple<UniTask.Awaiter>)state)
|
||||
{
|
||||
try
|
||||
{
|
||||
t.Item1.GetResult();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||
}
|
||||
}
|
||||
}, StateTuple.Create(awaiter));
|
||||
}
|
||||
}
|
||||
|
||||
public static void Forget(this UniTask task, Action<Exception> exceptionHandler, bool handleExceptionOnMainThread = true)
|
||||
{
|
||||
if (exceptionHandler == null)
|
||||
{
|
||||
Forget(task);
|
||||
}
|
||||
else
|
||||
{
|
||||
ForgetCoreWithCatch(task, exceptionHandler, handleExceptionOnMainThread).Forget();
|
||||
}
|
||||
}
|
||||
|
||||
static async UniTaskVoid ForgetCoreWithCatch(UniTask task, Action<Exception> exceptionHandler, bool handleExceptionOnMainThread)
|
||||
{
|
||||
try
|
||||
{
|
||||
await task;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (handleExceptionOnMainThread)
|
||||
{
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
await UniTask.SwitchToMainThread();
|
||||
#endif
|
||||
}
|
||||
exceptionHandler(ex);
|
||||
}
|
||||
catch (Exception ex2)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Forget<T>(this UniTask<T> task)
|
||||
{
|
||||
var awaiter = task.GetAwaiter();
|
||||
if (awaiter.IsCompleted)
|
||||
{
|
||||
try
|
||||
{
|
||||
awaiter.GetResult();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
awaiter.SourceOnCompleted(state =>
|
||||
{
|
||||
using (var t = (StateTuple<UniTask<T>.Awaiter>)state)
|
||||
{
|
||||
try
|
||||
{
|
||||
t.Item1.GetResult();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||
}
|
||||
}
|
||||
}, StateTuple.Create(awaiter));
|
||||
}
|
||||
}
|
||||
|
||||
public static void Forget<T>(this UniTask<T> task, Action<Exception> exceptionHandler, bool handleExceptionOnMainThread = true)
|
||||
{
|
||||
if (exceptionHandler == null)
|
||||
{
|
||||
task.Forget();
|
||||
}
|
||||
else
|
||||
{
|
||||
ForgetCoreWithCatch(task, exceptionHandler, handleExceptionOnMainThread).Forget();
|
||||
}
|
||||
}
|
||||
|
||||
static async UniTaskVoid ForgetCoreWithCatch<T>(UniTask<T> task, Action<Exception> exceptionHandler, bool handleExceptionOnMainThread)
|
||||
{
|
||||
try
|
||||
{
|
||||
await task;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (handleExceptionOnMainThread)
|
||||
{
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
await UniTask.SwitchToMainThread();
|
||||
#endif
|
||||
}
|
||||
exceptionHandler(ex);
|
||||
}
|
||||
catch (Exception ex2)
|
||||
{
|
||||
UniTaskScheduler.PublishUnobservedTaskException(ex2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async UniTask ContinueWith<T>(this UniTask<T> task, Action<T> continuationFunction)
|
||||
{
|
||||
continuationFunction(await task);
|
||||
}
|
||||
|
||||
public static async UniTask ContinueWith<T>(this UniTask<T> task, Func<T, UniTask> continuationFunction)
|
||||
{
|
||||
await continuationFunction(await task);
|
||||
}
|
||||
|
||||
public static async UniTask<TR> ContinueWith<T, TR>(this UniTask<T> task, Func<T, TR> continuationFunction)
|
||||
{
|
||||
return continuationFunction(await task);
|
||||
}
|
||||
|
||||
public static async UniTask<TR> ContinueWith<T, TR>(this UniTask<T> task, Func<T, UniTask<TR>> continuationFunction)
|
||||
{
|
||||
return await continuationFunction(await task);
|
||||
}
|
||||
|
||||
public static async UniTask ContinueWith(this UniTask task, Action continuationFunction)
|
||||
{
|
||||
await task;
|
||||
continuationFunction();
|
||||
}
|
||||
|
||||
public static async UniTask ContinueWith(this UniTask task, Func<UniTask> continuationFunction)
|
||||
{
|
||||
await task;
|
||||
await continuationFunction();
|
||||
}
|
||||
|
||||
public static async UniTask<T> ContinueWith<T>(this UniTask task, Func<T> continuationFunction)
|
||||
{
|
||||
await task;
|
||||
return continuationFunction();
|
||||
}
|
||||
|
||||
public static async UniTask<T> ContinueWith<T>(this UniTask task, Func<UniTask<T>> continuationFunction)
|
||||
{
|
||||
await task;
|
||||
return await continuationFunction();
|
||||
}
|
||||
|
||||
public static async UniTask<T> Unwrap<T>(this UniTask<UniTask<T>> task)
|
||||
{
|
||||
return await await task;
|
||||
}
|
||||
|
||||
public static async UniTask Unwrap(this UniTask<UniTask> task)
|
||||
{
|
||||
await await task;
|
||||
}
|
||||
|
||||
public static async UniTask<T> Unwrap<T>(this Task<UniTask<T>> task)
|
||||
{
|
||||
return await await task;
|
||||
}
|
||||
|
||||
public static async UniTask<T> Unwrap<T>(this Task<UniTask<T>> task, bool continueOnCapturedContext)
|
||||
{
|
||||
return await await task.ConfigureAwait(continueOnCapturedContext);
|
||||
}
|
||||
|
||||
public static async UniTask Unwrap(this Task<UniTask> task)
|
||||
{
|
||||
await await task;
|
||||
}
|
||||
|
||||
public static async UniTask Unwrap(this Task<UniTask> task, bool continueOnCapturedContext)
|
||||
{
|
||||
await await task.ConfigureAwait(continueOnCapturedContext);
|
||||
}
|
||||
|
||||
public static async UniTask<T> Unwrap<T>(this UniTask<Task<T>> task)
|
||||
{
|
||||
return await await task;
|
||||
}
|
||||
|
||||
public static async UniTask<T> Unwrap<T>(this UniTask<Task<T>> task, bool continueOnCapturedContext)
|
||||
{
|
||||
return await (await task).ConfigureAwait(continueOnCapturedContext);
|
||||
}
|
||||
|
||||
public static async UniTask Unwrap(this UniTask<Task> task)
|
||||
{
|
||||
await await task;
|
||||
}
|
||||
|
||||
public static async UniTask Unwrap(this UniTask<Task> task, bool continueOnCapturedContext)
|
||||
{
|
||||
await (await task).ConfigureAwait(continueOnCapturedContext);
|
||||
}
|
||||
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
|
||||
sealed class ToCoroutineEnumerator : IEnumerator
|
||||
{
|
||||
bool completed;
|
||||
UniTask task;
|
||||
Action<Exception> exceptionHandler = null;
|
||||
bool isStarted = false;
|
||||
ExceptionDispatchInfo exception;
|
||||
|
||||
public ToCoroutineEnumerator(UniTask task, Action<Exception> exceptionHandler)
|
||||
{
|
||||
completed = false;
|
||||
this.exceptionHandler = exceptionHandler;
|
||||
this.task = task;
|
||||
}
|
||||
|
||||
async UniTaskVoid RunTask(UniTask task)
|
||||
{
|
||||
try
|
||||
{
|
||||
await task;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (exceptionHandler != null)
|
||||
{
|
||||
exceptionHandler(ex);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.exception = ExceptionDispatchInfo.Capture(ex);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
completed = true;
|
||||
}
|
||||
}
|
||||
|
||||
public object Current => null;
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
if (!isStarted)
|
||||
{
|
||||
isStarted = true;
|
||||
RunTask(task).Forget();
|
||||
}
|
||||
|
||||
if (exception != null)
|
||||
{
|
||||
exception.Throw();
|
||||
return false;
|
||||
}
|
||||
|
||||
return !completed;
|
||||
}
|
||||
|
||||
void IEnumerator.Reset()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
sealed class ToCoroutineEnumerator<T> : IEnumerator
|
||||
{
|
||||
bool completed;
|
||||
Action<T> resultHandler = null;
|
||||
Action<Exception> exceptionHandler = null;
|
||||
bool isStarted = false;
|
||||
UniTask<T> task;
|
||||
object current = null;
|
||||
ExceptionDispatchInfo exception;
|
||||
|
||||
public ToCoroutineEnumerator(UniTask<T> task, Action<T> resultHandler, Action<Exception> exceptionHandler)
|
||||
{
|
||||
completed = false;
|
||||
this.task = task;
|
||||
this.resultHandler = resultHandler;
|
||||
this.exceptionHandler = exceptionHandler;
|
||||
}
|
||||
|
||||
async UniTaskVoid RunTask(UniTask<T> task)
|
||||
{
|
||||
try
|
||||
{
|
||||
var value = await task;
|
||||
current = value; // boxed if T is struct...
|
||||
if (resultHandler != null)
|
||||
{
|
||||
resultHandler(value);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (exceptionHandler != null)
|
||||
{
|
||||
exceptionHandler(ex);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.exception = ExceptionDispatchInfo.Capture(ex);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
completed = true;
|
||||
}
|
||||
}
|
||||
|
||||
public object Current => current;
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
if (!isStarted)
|
||||
{
|
||||
isStarted = true;
|
||||
RunTask(task).Forget();
|
||||
}
|
||||
|
||||
if (exception != null)
|
||||
{
|
||||
exception.Throw();
|
||||
return false;
|
||||
}
|
||||
|
||||
return !completed;
|
||||
}
|
||||
|
||||
void IEnumerator.Reset()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user