From b2d3423a335e9f701ac5567e4af7e54100e5e13a Mon Sep 17 00:00:00 2001 From: Yoshifumi Kawai Date: Sat, 18 Apr 2020 22:11:40 +0900 Subject: [PATCH] T | IUniTaskSource --- Assets/Scenes/SandboxMain.cs | 9 +- .../AsyncUniTaskMethodBuilder.cs | 48 +- Assets/UniRx.Async/UniTask.Factory.cs | 13 + Assets/UniRx.Async/UniTask.cs | 513 +++++++----------- Assets/UniRx.Async/UniTaskCompletionSource.cs | 21 +- 5 files changed, 275 insertions(+), 329 deletions(-) diff --git a/Assets/Scenes/SandboxMain.cs b/Assets/Scenes/SandboxMain.cs index f8c9e07..459aac0 100644 --- a/Assets/Scenes/SandboxMain.cs +++ b/Assets/Scenes/SandboxMain.cs @@ -40,10 +40,10 @@ public class SandboxMain : MonoBehaviour ucs = new UniTaskCompletionSource2(); - okButton.onClick.AddListener(UniTask.VoidUnityAction(async () => + okButton.onClick.AddListener(async () => { - await OuterAsync(true); - })); + await InnerAsync(false); + }); cancelButton.onClick.AddListener(async () => { @@ -84,7 +84,8 @@ public class SandboxMain : MonoBehaviour } else { - //UnityEngine.Debug.Log("Empty END"); + UnityEngine.Debug.Log("Empty END"); + throw new InvalidOperationException("FOOBARBAZ"); } } diff --git a/Assets/UniRx.Async/CompilerServices/AsyncUniTaskMethodBuilder.cs b/Assets/UniRx.Async/CompilerServices/AsyncUniTaskMethodBuilder.cs index 1d15f0b..31f9d34 100644 --- a/Assets/UniRx.Async/CompilerServices/AsyncUniTaskMethodBuilder.cs +++ b/Assets/UniRx.Async/CompilerServices/AsyncUniTaskMethodBuilder.cs @@ -298,10 +298,17 @@ namespace UniRx.Async.CompilerServices [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - if (promise == null) + if (promise != null) { - promise = AutoResetUniTaskCompletionSource.Create(); + return promise.Task; } + + if (runner == null) + { + return UniTask2.CompletedTask; + } + + promise = AutoResetUniTaskCompletionSource.Create(); return promise.Task; } } @@ -317,11 +324,14 @@ namespace UniRx.Async.CompilerServices runner = null; } - if (promise == null) + if (promise != null) { - promise = AutoResetUniTaskCompletionSource.Create(); + promise.SetException(exception); + } + else + { + promise = AutoResetUniTaskCompletionSource.CreateFromException(exception, out _); } - promise.SetException(exception); } // 4. SetResult @@ -335,11 +345,10 @@ namespace UniRx.Async.CompilerServices runner = null; } - if (promise == null) + if (promise != null) { - promise = AutoResetUniTaskCompletionSource.Create(); + promise.SetResult(); } - promise.SetResult(); } // 5. AwaitOnCompleted @@ -401,6 +410,7 @@ namespace UniRx.Async.CompilerServices // cache items. AutoResetUniTaskCompletionSource promise; IMoveNextRunner runner; + T result; // 1. Static Create method. [DebuggerHidden] @@ -416,10 +426,17 @@ namespace UniRx.Async.CompilerServices { get { - if (promise == null) + if (promise != null) { - promise = AutoResetUniTaskCompletionSource.Create(); + return promise.Task; } + + if (runner == null) + { + return UniTask2.FromResult(result); + } + + promise = AutoResetUniTaskCompletionSource.Create(); return promise.Task; } } @@ -437,9 +454,12 @@ namespace UniRx.Async.CompilerServices if (promise == null) { - promise = AutoResetUniTaskCompletionSource.Create(); + promise = AutoResetUniTaskCompletionSource.CreateFromException(exception, out _); + } + else + { + promise.SetException(exception); } - promise.SetException(exception); } // 4. SetResult @@ -455,8 +475,10 @@ namespace UniRx.Async.CompilerServices if (promise == null) { - promise = AutoResetUniTaskCompletionSource.Create(); + this.result = result; + return; } + promise.SetResult(result); } diff --git a/Assets/UniRx.Async/UniTask.Factory.cs b/Assets/UniRx.Async/UniTask.Factory.cs index 291ce5c..5bc0b84 100644 --- a/Assets/UniRx.Async/UniTask.Factory.cs +++ b/Assets/UniRx.Async/UniTask.Factory.cs @@ -128,5 +128,18 @@ namespace UniRx.Async public static readonly UniTask MinusOne = UniTask.FromResult(-1); public static readonly UniTask One = UniTask.FromResult(1); } + + + + internal static class CompletedTasks2 + { + public static readonly UniTask2 Completed = new UniTask2(); + public static readonly UniTask2 AsyncUnit = UniTask2.FromResult(UniRx.Async.AsyncUnit.Default); + public static readonly UniTask2 True = UniTask2.FromResult(true); + public static readonly UniTask2 False = UniTask2.FromResult(false); + public static readonly UniTask2 Zero = UniTask2.FromResult(0); + public static readonly UniTask2 MinusOne = UniTask2.FromResult(-1); + public static readonly UniTask2 One = UniTask2.FromResult(1); + } } #endif \ No newline at end of file diff --git a/Assets/UniRx.Async/UniTask.cs b/Assets/UniRx.Async/UniTask.cs index 72779bd..78cd6e2 100644 --- a/Assets/UniRx.Async/UniTask.cs +++ b/Assets/UniRx.Async/UniTask.cs @@ -29,9 +29,17 @@ namespace UniRx.Async //return new ValueTask(DelayPromiseCore2.Create(frameCount, timing, cancellationToken, out var token), token); } + public static readonly UniTask2 CompletedTask = new UniTask2(); + + public static UniTask2 FromResult(T result) + { + return new UniTask2(result); + } } + + public class DelayPromiseCore2 : IUniTaskSource, IPlayerLoopItem, IPromisePoolItem { static readonly PromisePool pool = new PromisePool(); @@ -70,6 +78,7 @@ namespace UniRx.Async { try { + TaskTracker2.RemoveTracking(this); core.GetResult(token); } finally @@ -97,14 +106,12 @@ namespace UniRx.Async { if (cancellationToken.IsCancellationRequested) { - TaskTracker2.RemoveTracking(this); core.SetCancellation(cancellationToken); return false; } if (currentFrameCount == delayFrameCount) { - TaskTracker2.RemoveTracking(this); core.SetResult(null); return false; } @@ -126,25 +133,30 @@ namespace UniRx.Async + internal static class AwaiterActions + { + internal static readonly Action InvokeActionDelegate = InvokeAction; - + static void InvokeAction(object state) + { + ((Action)state).Invoke(); + } + } /// /// Lightweight unity specified task-like object. /// - [AsyncMethodBuilder(typeof(AsyncUniTask2MethodBuilder))] // TODO:AsyncUniTask2 - public partial struct UniTask2 + [AsyncMethodBuilder(typeof(AsyncUniTask2MethodBuilder))] + public readonly partial struct UniTask2 { - // static readonly UniTask DefaultAsyncUnitTask = new UniTask(AsyncUnit.Default); - - readonly IUniTaskSource awaiter; + readonly IUniTaskSource source; readonly short token; [DebuggerHidden] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public UniTask2(IUniTaskSource awaiter, short token) + public UniTask2(IUniTaskSource source, short token) { - this.awaiter = awaiter; + this.source = source; this.token = token; } @@ -154,7 +166,8 @@ namespace UniRx.Async [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - return awaiter.GetStatus(token); + if (source == null) return AwaiterStatus.Succeeded; + return source.GetStatus(token); } } @@ -165,154 +178,112 @@ namespace UniRx.Async return new Awaiter(this); } - [DebuggerHidden] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - void GetResult() + /// + /// returns (bool IsCanceled) instead of throws OperationCanceledException. + /// + public UniTask2 SuppressCancellationThrow() { - awaiter.GetResult(token); + var status = Status; + if (status == AwaiterStatus.Succeeded) return CompletedTasks2.False; + if (status == AwaiterStatus.Canceled) return CompletedTasks2.True; + return new UniTask2(new IsCanceledSource(source), token); } - // TODO:can be suppress? - - ///// - ///// returns (bool IsCanceled) instead of throws OperationCanceledException. - ///// - //public UniTask SuppressCancellationThrow() - //{ - // var status = Status; - // if (status == AwaiterStatus.Succeeded) return CompletedTasks.False; - // if (status == AwaiterStatus.Canceled) return CompletedTasks.True; - // //return new UniTask(new IsCanceledAwaiter(awaiter)); - //} - public override string ToString() { - var status = this.awaiter.UnsafeGetStatus(); - return (status == AwaiterStatus.Succeeded) ? "()" : "(" + status + ")"; + if (source == null) return "()"; + return "(" + source.UnsafeGetStatus() + ")"; } - //public static implicit operator UniTask(UniTask2 task) - //{ - // // TODO: - // throw new NotImplementedException(); + // TODO:AsTask??? - // //if (task.awaiter != null) - // //{ - // // if (task.awaiter.IsCompleted) - // // { - // // return DefaultAsyncUnitTask; - // // } - // // else - // // { - // // // UniTask -> UniTask is free but UniTask -> UniTask requires wrapping cost. - // // return new UniTask(new AsyncUnitAwaiter(task.awaiter)); - // // } - // //} - // //else - // //{ - // // return DefaultAsyncUnitTask; - // //} - //} - - //class AsyncUnitAwaiter : IAwaiter - //{ - // readonly IAwaiter2 awaiter; - - // public AsyncUnitAwaiter(IAwaiter2 awaiter) - // { - // this.awaiter = awaiter; - // } - - // public bool IsCompleted => awaiter.IsCompleted; - - // public AwaiterStatus Status => awaiter.Status; - - // public AsyncUnit GetResult() - // { - // awaiter.GetResult(); - // return AsyncUnit.Default; - // } - - // public void OnCompleted(Action continuation) - // { - // awaiter.OnCompleted(continuation); - // } - - // public void UnsafeOnCompleted(Action continuation) - // { - // awaiter.UnsafeOnCompleted(continuation); - // } - - // void IAwaiter.GetResult() - // { - // awaiter.GetResult(); - // } - //} - - class IsCanceledAwaiter : IUniTaskSource + public static implicit operator UniTask2(UniTask2 task) { - readonly IUniTaskSource awaiter; + if (task.source == null) return CompletedTasks2.AsyncUnit; - public IsCanceledAwaiter(IUniTaskSource awaiter) + var status = task.source.GetStatus(task.token); + if (status.IsCompletedSuccessfully()) { - this.awaiter = awaiter; + return CompletedTasks2.AsyncUnit; } - //public bool IsCompleted => awaiter.IsCompleted; + return new UniTask2(new AsyncUnitSource(task.source), task.token); + } - //public AwaiterStatus Status => awaiter.Status; + class AsyncUnitSource : IUniTaskSource + { + readonly IUniTaskSource source; - //public bool GetResult() - //{ - // if (awaiter.Status == AwaiterStatus.Canceled) - // { - // return true; - // } - // awaiter.GetResult(); - // return false; - //} - - //public void OnCompleted(Action continuation) - //{ - // awaiter.OnCompleted(continuation); - //} - - //public void UnsafeOnCompleted(Action continuation) - //{ - // awaiter.UnsafeOnCompleted(continuation); - //} - - //void IAwaiter.GetResult() - //{ - // awaiter.GetResult(); - //} - - public void GetResult(short token) + public AsyncUnitSource(IUniTaskSource source) { - // TODO: bool - if (awaiter.GetStatus(token) == AwaiterStatus.Canceled) - { - //return true; - } + this.source = source; + } - awaiter.GetResult(token); - // return false - throw new NotImplementedException(); + public AsyncUnit GetResult(short token) + { + source.GetResult(token); + return AsyncUnit.Default; } public AwaiterStatus GetStatus(short token) { - return awaiter.GetStatus(token); - } - - public AwaiterStatus UnsafeGetStatus() - { - return awaiter.UnsafeGetStatus(); + return source.GetStatus(token); } public void OnCompleted(Action continuation, object state, short token) { - awaiter.OnCompleted(continuation, state, token); + source.OnCompleted(continuation, state, token); + } + + public AwaiterStatus UnsafeGetStatus() + { + return source.UnsafeGetStatus(); + } + + void IUniTaskSource.GetResult(short token) + { + GetResult(token); + } + } + + class IsCanceledSource : IUniTaskSource + { + readonly IUniTaskSource source; + + public IsCanceledSource(IUniTaskSource source) + { + this.source = source; + } + + public bool GetResult(short token) + { + if (source.GetStatus(token) == AwaiterStatus.Canceled) + { + return true; + } + + source.GetResult(token); + return false; + } + + void IUniTaskSource.GetResult(short token) + { + GetResult(token); + } + + public AwaiterStatus GetStatus(short token) + { + return source.GetStatus(token); + } + + public AwaiterStatus UnsafeGetStatus() + { + return source.UnsafeGetStatus(); + } + + public void OnCompleted(Action continuation, object state, short token) + { + source.OnCompleted(continuation, state, token); } } @@ -337,69 +308,70 @@ namespace UniRx.Async } } - public AwaiterStatus Status - { - [DebuggerHidden] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return task.Status; - } - } - [DebuggerHidden] [MethodImpl(MethodImplOptions.AggressiveInlining)] public void GetResult() { - task.GetResult(); + if (task.source == null) return; + task.source.GetResult(task.token); } [DebuggerHidden] [MethodImpl(MethodImplOptions.AggressiveInlining)] public void OnCompleted(Action continuation) { - task.awaiter.OnCompleted(AwaiterActions.InvokeActionDelegate, continuation, task.token); + if (task.source == null) + { + continuation(); + } + else + { + task.source.OnCompleted(AwaiterActions.InvokeActionDelegate, continuation, task.token); + } } [DebuggerHidden] [MethodImpl(MethodImplOptions.AggressiveInlining)] public void UnsafeOnCompleted(Action continuation) { - task.awaiter.OnCompleted(AwaiterActions.InvokeActionDelegate, continuation, task.token); + if (task.source == null) + { + continuation(); + } + else + { + task.source.OnCompleted(AwaiterActions.InvokeActionDelegate, continuation, task.token); + } } } } - internal static class AwaiterActions - { - internal static readonly Action InvokeActionDelegate = InvokeAction; - - static void InvokeAction(object state) - { - ((Action)state).Invoke(); - } - } - - - - /// /// Lightweight unity specified task-like object. /// - [AsyncMethodBuilder(typeof(AsyncUniTask2MethodBuilder))] // TODO:AsyncUniTask2~T - public struct UniTask2 + [AsyncMethodBuilder(typeof(AsyncUniTask2MethodBuilder<>))] + public readonly struct UniTask2 { - // static readonly UniTask DefaultAsyncUnitTask = new UniTask(AsyncUnit.Default); - - readonly IUniTaskSource awaiter; + readonly IUniTaskSource source; + readonly T result; readonly short token; [DebuggerHidden] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public UniTask2(IUniTaskSource awaiter, short token) + public UniTask2(T result) { - this.awaiter = awaiter; + this.source = default; + this.token = default; + this.result = result; + } + + [DebuggerHidden] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public UniTask2(IUniTaskSource source, short token) + { + this.source = source; this.token = token; + this.result = default; } public AwaiterStatus Status @@ -408,7 +380,7 @@ namespace UniRx.Async [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - return awaiter.GetStatus(token); + return (source == null) ? AwaiterStatus.Succeeded : source.GetStatus(token); } } @@ -419,154 +391,77 @@ namespace UniRx.Async return new Awaiter(this); } - [DebuggerHidden] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - T GetResult() + // TODO:AsTask??? + + /// + /// returns (bool IsCanceled, T Result) instead of throws OperationCanceledException. + /// + public UniTask2<(bool IsCanceled, T Result)> SuppressCancellationThrow() { - return awaiter.GetResult(token); + if (source == null) + { + return new UniTask2<(bool IsCanceled, T Result)>((false, result)); + } + + return new UniTask2<(bool, T)>(new IsCanceledSource(source), token); } - // TODO:can be suppress? - - ///// - ///// returns (bool IsCanceled) instead of throws OperationCanceledException. - ///// - //public UniTask SuppressCancellationThrow() - //{ - // var status = Status; - // if (status == AwaiterStatus.Succeeded) return CompletedTasks.False; - // if (status == AwaiterStatus.Canceled) return CompletedTasks.True; - // //return new UniTask(new IsCanceledAwaiter(awaiter)); - //} - public override string ToString() { - var status = this.awaiter.UnsafeGetStatus(); - return (status == AwaiterStatus.Succeeded) ? "()" : "(" + status + ")"; + return (this.source == null) ? result?.ToString() + : "(" + this.source.UnsafeGetStatus() + ")"; } - //public static implicit operator UniTask(UniTask2 task) - //{ - // // TODO: - // throw new NotImplementedException(); - - // //if (task.awaiter != null) - // //{ - // // if (task.awaiter.IsCompleted) - // // { - // // return DefaultAsyncUnitTask; - // // } - // // else - // // { - // // // UniTask -> UniTask is free but UniTask -> UniTask requires wrapping cost. - // // return new UniTask(new AsyncUnitAwaiter(task.awaiter)); - // // } - // //} - // //else - // //{ - // // return DefaultAsyncUnitTask; - // //} - //} - - //class AsyncUnitAwaiter : IAwaiter - //{ - // readonly IAwaiter2 awaiter; - - // public AsyncUnitAwaiter(IAwaiter2 awaiter) - // { - // this.awaiter = awaiter; - // } - - // public bool IsCompleted => awaiter.IsCompleted; - - // public AwaiterStatus Status => awaiter.Status; - - // public AsyncUnit GetResult() - // { - // awaiter.GetResult(); - // return AsyncUnit.Default; - // } - - // public void OnCompleted(Action continuation) - // { - // awaiter.OnCompleted(continuation); - // } - - // public void UnsafeOnCompleted(Action continuation) - // { - // awaiter.UnsafeOnCompleted(continuation); - // } - - // void IAwaiter.GetResult() - // { - // awaiter.GetResult(); - // } - //} - - class IsCanceledAwaiter : IUniTaskSource + class IsCanceledSource : IUniTaskSource<(bool, T)> { - readonly IUniTaskSource awaiter; + readonly IUniTaskSource source; - public IsCanceledAwaiter(IUniTaskSource awaiter) + [DebuggerHidden] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public IsCanceledSource(IUniTaskSource source) { - this.awaiter = awaiter; + this.source = source; } - //public bool IsCompleted => awaiter.IsCompleted; - - //public AwaiterStatus Status => awaiter.Status; - - //public bool GetResult() - //{ - // if (awaiter.Status == AwaiterStatus.Canceled) - // { - // return true; - // } - // awaiter.GetResult(); - // return false; - //} - - //public void OnCompleted(Action continuation) - //{ - // awaiter.OnCompleted(continuation); - //} - - //public void UnsafeOnCompleted(Action continuation) - //{ - // awaiter.UnsafeOnCompleted(continuation); - //} - - //void IAwaiter.GetResult() - //{ - // awaiter.GetResult(); - //} - - public void GetResult(short token) + [DebuggerHidden] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public (bool, T) GetResult(short token) { - // TODO: bool - if (awaiter.GetStatus(token) == AwaiterStatus.Canceled) + if (source.GetStatus(token) == AwaiterStatus.Canceled) { - //return true; + return (true, default); } - awaiter.GetResult(token); - // return false - throw new NotImplementedException(); + var result = source.GetResult(token); + return (false, result); } + [DebuggerHidden] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + void IUniTaskSource.GetResult(short token) + { + GetResult(token); + } + + [DebuggerHidden] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public AwaiterStatus GetStatus(short token) { - return awaiter.GetStatus(token); + return source.GetStatus(token); } + [DebuggerHidden] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public AwaiterStatus UnsafeGetStatus() { - return awaiter.UnsafeGetStatus(); + return source.UnsafeGetStatus(); } + [DebuggerHidden] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void OnCompleted(Action continuation, object state, short token) { - awaiter.OnCompleted(continuation, state, token); + source.OnCompleted(continuation, state, token); } } @@ -591,35 +486,49 @@ namespace UniRx.Async } } - public AwaiterStatus Status - { - [DebuggerHidden] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return task.Status; - } - } - [DebuggerHidden] [MethodImpl(MethodImplOptions.AggressiveInlining)] public T GetResult() { - return task.GetResult(); + var s = task.source; + if (s == null) + { + return task.result; + } + else + { + return s.GetResult(task.token); + } } [DebuggerHidden] [MethodImpl(MethodImplOptions.AggressiveInlining)] public void OnCompleted(Action continuation) { - task.awaiter.OnCompleted(AwaiterActions.InvokeActionDelegate, continuation, task.token); + var s = task.source; + if (s == null) + { + continuation(); + } + else + { + s.OnCompleted(AwaiterActions.InvokeActionDelegate, continuation, task.token); + } } [DebuggerHidden] [MethodImpl(MethodImplOptions.AggressiveInlining)] public void UnsafeOnCompleted(Action continuation) { - task.awaiter.OnCompleted(AwaiterActions.InvokeActionDelegate, continuation, task.token); + var s = task.source; + if (s == null) + { + continuation(); + } + else + { + s.OnCompleted(AwaiterActions.InvokeActionDelegate, continuation, task.token); + } } } } @@ -1045,7 +954,7 @@ namespace UniRx.Async readonly UniTask task; [DebuggerHidden] - public Awaiter(UniTask task) + public Awaiter(in UniTask task) { this.task = task; } diff --git a/Assets/UniRx.Async/UniTaskCompletionSource.cs b/Assets/UniRx.Async/UniTaskCompletionSource.cs index 9432666..aa42750 100644 --- a/Assets/UniRx.Async/UniTaskCompletionSource.cs +++ b/Assets/UniRx.Async/UniTaskCompletionSource.cs @@ -693,8 +693,9 @@ namespace UniRx.Async public static AutoResetUniTaskCompletionSource Create() { - // TODO:Add TaskTracker - return pool.TryRent() ?? new AutoResetUniTaskCompletionSource(); + var value = pool.TryRent() ?? new AutoResetUniTaskCompletionSource(); + TaskTracker2.TrackActiveTask(value, 2); + return value; } public static AutoResetUniTaskCompletionSource CreateFromCanceled(CancellationToken cancellationToken, out short token) @@ -748,7 +749,7 @@ namespace UniRx.Async { try { - // TODO:Remove TaskTracker + TaskTracker2.RemoveTracking(this); core.GetResult(token); } finally @@ -795,7 +796,7 @@ namespace UniRx.Async public UniTaskCompletionSource2() { - // TODO: TaskTracker.TrackActiveTask + TaskTracker2.TrackActiveTask(this, 2); } [Conditional("UNITY_EDITOR")] @@ -804,8 +805,7 @@ namespace UniRx.Async if (!handled) { handled = true; - // TODO: - // TaskTracker.RemoveTracking(this); + TaskTracker2.RemoveTracking(this); } } @@ -819,9 +819,9 @@ namespace UniRx.Async public void Reset() { - // TODO:Reset, reactive tracker: TaskTracker.TrackActiveTask handled = false; core.Reset(); + TaskTracker2.TrackActiveTask(this, 2); } public void SetResult(T result) @@ -884,8 +884,9 @@ namespace UniRx.Async public static AutoResetUniTaskCompletionSource Create() { - // TODO:Add TaskTracker - return pool.TryRent() ?? new AutoResetUniTaskCompletionSource(); + var result = pool.TryRent() ?? new AutoResetUniTaskCompletionSource(); + TaskTracker2.TrackActiveTask(result, 2); + return result; } public static AutoResetUniTaskCompletionSource CreateFromCanceled(CancellationToken cancellationToken, out short token) @@ -939,7 +940,7 @@ namespace UniRx.Async { try { - // TODO:Remove TaskTracker + TaskTracker2.RemoveTracking(this); return core.GetResult(token); } finally