timer and delay skip current frame

master
neuecc 2020-06-09 11:25:45 +09:00
parent 4d4466e801
commit 0c33977f5a
13 changed files with 1130 additions and 448 deletions

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Threading; using System.Threading;
using UnityEngine;
namespace Cysharp.Threading.Tasks.Linq namespace Cysharp.Threading.Tasks.Linq
{ {
@ -22,16 +23,34 @@ namespace Cysharp.Threading.Tasks.Linq
public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update) public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
{ {
if (dueTimeFrameCount < 0)
{
throw new ArgumentOutOfRangeException("Delay does not allow minus delayFrameCount. dueTimeFrameCount:" + dueTimeFrameCount);
}
return new TimerFrame(dueTimeFrameCount, null, updateTiming); return new TimerFrame(dueTimeFrameCount, null, updateTiming);
} }
public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, int periodFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update) public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, int periodFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
{ {
if (dueTimeFrameCount < 0)
{
throw new ArgumentOutOfRangeException("Delay does not allow minus delayFrameCount. dueTimeFrameCount:" + dueTimeFrameCount);
}
if (periodFrameCount < 0)
{
throw new ArgumentOutOfRangeException("Delay does not allow minus periodFrameCount. periodFrameCount:" + dueTimeFrameCount);
}
return new TimerFrame(dueTimeFrameCount, periodFrameCount, updateTiming); return new TimerFrame(dueTimeFrameCount, periodFrameCount, updateTiming);
} }
public static IUniTaskAsyncEnumerable<AsyncUnit> IntervalFrame(int intervalFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update) public static IUniTaskAsyncEnumerable<AsyncUnit> IntervalFrame(int intervalFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
{ {
if (intervalFrameCount < 0)
{
throw new ArgumentOutOfRangeException("Delay does not allow minus intervalFrameCount. intervalFrameCount:" + intervalFrameCount);
}
return new TimerFrame(intervalFrameCount, intervalFrameCount, updateTiming); return new TimerFrame(intervalFrameCount, intervalFrameCount, updateTiming);
} }
} }
@ -64,6 +83,7 @@ namespace Cysharp.Threading.Tasks.Linq
readonly bool ignoreTimeScale; readonly bool ignoreTimeScale;
CancellationToken cancellationToken; CancellationToken cancellationToken;
int initialFrame;
float elapsed; float elapsed;
bool dueTimePhase; bool dueTimePhase;
bool completed; bool completed;
@ -80,6 +100,7 @@ namespace Cysharp.Threading.Tasks.Linq
if (this.period <= 0) this.period = 1; if (this.period <= 0) this.period = 1;
} }
this.initialFrame = Time.frameCount;
this.dueTimePhase = true; this.dueTimePhase = true;
this.updateTiming = updateTiming; this.updateTiming = updateTiming;
this.ignoreTimeScale = ignoreTimeScale; this.ignoreTimeScale = ignoreTimeScale;
@ -119,9 +140,19 @@ namespace Cysharp.Threading.Tasks.Linq
return false; return false;
} }
elapsed += (ignoreTimeScale) ? UnityEngine.Time.unscaledDeltaTime : UnityEngine.Time.deltaTime;
if (dueTimePhase) if (dueTimePhase)
{ {
if (elapsed == 0)
{
// skip in initial frame.
if (initialFrame == Time.frameCount)
{
return true;
}
}
elapsed += (ignoreTimeScale) ? UnityEngine.Time.unscaledDeltaTime : UnityEngine.Time.deltaTime;
if (elapsed >= dueTime) if (elapsed >= dueTime)
{ {
dueTimePhase = false; dueTimePhase = false;
@ -137,6 +168,8 @@ namespace Cysharp.Threading.Tasks.Linq
return false; return false;
} }
elapsed += (ignoreTimeScale) ? UnityEngine.Time.unscaledDeltaTime : UnityEngine.Time.deltaTime;
if (elapsed >= period) if (elapsed >= period)
{ {
completionSource.TrySetResult(true); completionSource.TrySetResult(true);
@ -172,6 +205,7 @@ namespace Cysharp.Threading.Tasks.Linq
readonly int? periodFrameCount; readonly int? periodFrameCount;
CancellationToken cancellationToken; CancellationToken cancellationToken;
int initialFrame;
int currentFrame; int currentFrame;
bool dueTimePhase; bool dueTimePhase;
bool completed; bool completed;
@ -185,6 +219,7 @@ namespace Cysharp.Threading.Tasks.Linq
if (periodFrameCount <= 0) periodFrameCount = 1; if (periodFrameCount <= 0) periodFrameCount = 1;
} }
this.initialFrame = Time.frameCount;
this.dueTimePhase = true; this.dueTimePhase = true;
this.dueTimeFrameCount = dueTimeFrameCount; this.dueTimeFrameCount = dueTimeFrameCount;
this.periodFrameCount = periodFrameCount; this.periodFrameCount = periodFrameCount;
@ -228,10 +263,29 @@ namespace Cysharp.Threading.Tasks.Linq
if (dueTimePhase) if (dueTimePhase)
{ {
if (currentFrame++ >= dueTimeFrameCount) if (currentFrame == 0)
{
if (dueTimeFrameCount == 0)
{ {
dueTimePhase = false; dueTimePhase = false;
completionSource.TrySetResult(true); completionSource.TrySetResult(true);
return true;
}
// skip in initial frame.
if (initialFrame == Time.frameCount)
{
return true;
}
}
if (++currentFrame >= dueTimeFrameCount)
{
dueTimePhase = false;
completionSource.TrySetResult(true);
}
else
{
} }
} }
else else

View File

@ -303,11 +303,12 @@ namespace Cysharp.Threading.Tasks
TaskPool.RegisterSizeGetter(typeof(DelayFramePromise), () => pool.Size); TaskPool.RegisterSizeGetter(typeof(DelayFramePromise), () => pool.Size);
} }
int initialFrame;
int delayFrameCount; int delayFrameCount;
CancellationToken cancellationToken; CancellationToken cancellationToken;
int currentFrameCount; int currentFrameCount;
UniTaskCompletionSourceCore<object> core; UniTaskCompletionSourceCore<AsyncUnit> core;
DelayFramePromise() DelayFramePromise()
{ {
@ -327,6 +328,7 @@ namespace Cysharp.Threading.Tasks
result.delayFrameCount = delayFrameCount; result.delayFrameCount = delayFrameCount;
result.cancellationToken = cancellationToken; result.cancellationToken = cancellationToken;
result.initialFrame = Time.frameCount;
TaskTracker.TrackActiveTask(result, 3); TaskTracker.TrackActiveTask(result, 3);
@ -371,13 +373,27 @@ namespace Cysharp.Threading.Tasks
return false; return false;
} }
if (currentFrameCount == delayFrameCount) if (currentFrameCount == 0)
{ {
core.TrySetResult(null); if (delayFrameCount == 0) // same as Yield
{
core.TrySetResult(AsyncUnit.Default);
return false;
}
// skip in initial frame.
if (initialFrame == Time.frameCount)
{
return true;
}
}
if (++currentFrameCount >= delayFrameCount)
{
core.TrySetResult(AsyncUnit.Default);
return false; return false;
} }
currentFrameCount++;
return true; return true;
} }
@ -410,6 +426,7 @@ namespace Cysharp.Threading.Tasks
TaskPool.RegisterSizeGetter(typeof(DelayPromise), () => pool.Size); TaskPool.RegisterSizeGetter(typeof(DelayPromise), () => pool.Size);
} }
int initialFrame;
float delayFrameTimeSpan; float delayFrameTimeSpan;
float elapsed; float elapsed;
CancellationToken cancellationToken; CancellationToken cancellationToken;
@ -435,6 +452,7 @@ namespace Cysharp.Threading.Tasks
result.elapsed = 0.0f; result.elapsed = 0.0f;
result.delayFrameTimeSpan = (float)delayFrameTimeSpan.TotalSeconds; result.delayFrameTimeSpan = (float)delayFrameTimeSpan.TotalSeconds;
result.cancellationToken = cancellationToken; result.cancellationToken = cancellationToken;
result.initialFrame = Time.frameCount;
TaskTracker.TrackActiveTask(result, 3); TaskTracker.TrackActiveTask(result, 3);
@ -479,6 +497,14 @@ namespace Cysharp.Threading.Tasks
return false; return false;
} }
if (elapsed == 0.0f)
{
if (initialFrame == Time.frameCount)
{
return true;
}
}
elapsed += Time.deltaTime; elapsed += Time.deltaTime;
if (elapsed >= delayFrameTimeSpan) if (elapsed >= delayFrameTimeSpan)
{ {
@ -520,6 +546,7 @@ namespace Cysharp.Threading.Tasks
float delayFrameTimeSpan; float delayFrameTimeSpan;
float elapsed; float elapsed;
int initialFrame;
CancellationToken cancellationToken; CancellationToken cancellationToken;
UniTaskCompletionSourceCore<object> core; UniTaskCompletionSourceCore<object> core;
@ -542,6 +569,7 @@ namespace Cysharp.Threading.Tasks
result.elapsed = 0.0f; result.elapsed = 0.0f;
result.delayFrameTimeSpan = (float)delayFrameTimeSpan.TotalSeconds; result.delayFrameTimeSpan = (float)delayFrameTimeSpan.TotalSeconds;
result.initialFrame = Time.frameCount;
result.cancellationToken = cancellationToken; result.cancellationToken = cancellationToken;
TaskTracker.TrackActiveTask(result, 3); TaskTracker.TrackActiveTask(result, 3);
@ -587,6 +615,14 @@ namespace Cysharp.Threading.Tasks
return false; return false;
} }
if (elapsed == 0.0f)
{
if (initialFrame == Time.frameCount)
{
return true;
}
}
elapsed += Time.unscaledDeltaTime; elapsed += Time.unscaledDeltaTime;
if (elapsed >= delayFrameTimeSpan) if (elapsed >= delayFrameTimeSpan)
{ {

View File

@ -378,7 +378,39 @@ public class SandboxMain : MonoBehaviour
private void FixedUpdate() private void FixedUpdate()
{ {
Debug.Log("FixedUpdate:" + Time.frameCount + ", " + PlayerLoopInfo.CurrentLoopType); // Debug.Log("FixedUpdate:" + Time.frameCount + ", " + PlayerLoopInfo.CurrentLoopType);
}
async UniTaskVoid DelayFrame3_Pre()
{
await UniTask.Yield(PlayerLoopTiming.PreUpdate);
Debug.Log("Before framecount:" + Time.frameCount);
await UniTask.DelayFrame(3);
Debug.Log("After framecount:" + Time.frameCount);
}
async UniTaskVoid DelayFrame3_Post()
{
await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
Debug.Log("Before framecount:" + Time.frameCount);
await UniTask.DelayFrame(3);
Debug.Log("After framecount:" + Time.frameCount);
}
async UniTask TestCoroutine()
{
await UniTask.Yield();
throw new Exception("foobarbaz");
}
async UniTask DelayCheck()
{
await UniTask.Yield(PlayerLoopTiming.PreUpdate);
Debug.Log("before");
var t = UniTask.Delay(TimeSpan.FromSeconds(1), ignoreTimeScale: false);
await t;
Debug.Log("after");
} }
@ -386,13 +418,29 @@ public class SandboxMain : MonoBehaviour
{ {
PlayerLoopInfo.Inject(); PlayerLoopInfo.Inject();
_ = AsyncFixedUpdate(); //_ = AsyncFixedUpdate();
StartCoroutine(CoroutineFixedUpdate()); //StartCoroutine(CoroutineFixedUpdate());
//StartCoroutine(TestCoroutine().ToCoroutine());
Application.logMessageReceived += Application_logMessageReceived;
okButton.onClick.AddListener(UniTask.UnityAction(async () => okButton.onClick.AddListener(UniTask.UnityAction(async () =>
{ {
{
var xs = await UniTaskAsyncEnumerable.TimerFrame(1).ToArrayAsync();
}
Debug.Log("------------------");
{
var xs = await UniTaskAsyncEnumerable.TimerFrame(1).ToArrayAsync();
}
//await DelayCheck();
/* /*
UnityEngine.Debug.Log("click:" + PlayerLoopInfo.CurrentLoopType); UnityEngine.Debug.Log("click:" + PlayerLoopInfo.CurrentLoopType);
StartCoroutine(CoroutineRun()); StartCoroutine(CoroutineRun());
@ -401,8 +449,8 @@ public class SandboxMain : MonoBehaviour
_ = AsyncLastUpdate(); _ = AsyncLastUpdate();
_ = AsyncLastLast(); _ = AsyncLastLast();
*/ */
await UniTask.Yield(); //await UniTask.Yield();
_ = Test2(); //_ = Test2();
// EarlyUpdate.ExecuteMainThreadJobs // EarlyUpdate.ExecuteMainThreadJobs
// _ = Test2(); // _ = Test2();
@ -420,10 +468,17 @@ public class SandboxMain : MonoBehaviour
//StartCoroutine(CoroutineRun2()); //StartCoroutine(CoroutineRun2());
////StartCoroutine(CoroutineRun()); ////StartCoroutine(CoroutineRun());
//UnityEngine.Debug.Log("FOO?"); //UnityEngine.Debug.Log("FOO?");
//_ = DelayFrame3_Pre();
//await UniTask.Yield();
})); }));
cancelButton.onClick.AddListener(UniTask.UnityAction(async () => cancelButton.onClick.AddListener(UniTask.UnityAction(async () =>
{ {
_ = DelayFrame3_Post();
await UniTask.Yield();
//await UniTask.Yield(PlayerLoopTiming.LastPreUpdate); //await UniTask.Yield(PlayerLoopTiming.LastPreUpdate);
//UnityEngine.Debug.Log("before update:" + Time.frameCount); //UnityEngine.Debug.Log("before update:" + Time.frameCount);
//await UniTask.NextFrame(); //await UniTask.NextFrame();
@ -435,13 +490,13 @@ public class SandboxMain : MonoBehaviour
//UnityEngine.Debug.Log("click:" + PlayerLoopInfo.CurrentLoopType); //UnityEngine.Debug.Log("click:" + PlayerLoopInfo.CurrentLoopType);
//_ = Yieldding(); //_ = Yieldding();
var cts = new CancellationTokenSource(); //var cts = new CancellationTokenSource();
UnityEngine.Debug.Log("click:" + PlayerLoopInfo.CurrentLoopType + ":" + Time.frameCount); //UnityEngine.Debug.Log("click:" + PlayerLoopInfo.CurrentLoopType + ":" + Time.frameCount);
var la = SceneManager.LoadSceneAsync("Scenes/ExceptionExamples").WithCancellation(cts.Token); //var la = SceneManager.LoadSceneAsync("Scenes/ExceptionExamples").WithCancellation(cts.Token);
//cts.Cancel(); ////cts.Cancel();
await la; //await la;
UnityEngine.Debug.Log("End LoadSceneAsync" + PlayerLoopInfo.CurrentLoopType + ":" + Time.frameCount); //UnityEngine.Debug.Log("End LoadSceneAsync" + PlayerLoopInfo.CurrentLoopType + ":" + Time.frameCount);
})); }));
//return; //return;
@ -571,6 +626,16 @@ public class SandboxMain : MonoBehaviour
} }
private void Application_logMessageReceived2(string condition, string stackTrace, LogType type)
{
throw new NotImplementedException();
}
private void Application_logMessageReceived1(string condition, string stackTrace, LogType type)
{
throw new NotImplementedException();
}
async UniTaskVoid UpdateUniTask() async UniTaskVoid UpdateUniTask()
{ {
while (true) while (true)

View File

@ -269,7 +269,8 @@ namespace Cysharp.Threading.TasksTests
var first = Time.frameCount; var first = Time.frameCount;
var canceled = await UniTask.DelayFrame(100, cancellationToken: cts.Token).SuppressCancellationThrow(); var canceled = await UniTask.DelayFrame(100, cancellationToken: cts.Token).SuppressCancellationThrow();
(Time.frameCount - first).Should().Be(11); // 10 frame canceled var r = (Time.frameCount - first);
(9 < r && r < 11).Should().BeTrue();
canceled.Should().Be(true); canceled.Should().Be(true);
}); });

View File

@ -0,0 +1,97 @@
using Cysharp.Threading.Tasks;
using Cysharp.Threading.Tasks.Linq;
using FluentAssertions;
using NUnit.Framework;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.TestTools;
namespace Cysharp.Threading.TasksTests
{
public class Cachelike
{
[UnityTest]
public IEnumerator Check() => UniTask.ToCoroutine(async () =>
{
{
var v = await CachedCheck("foo", 10);
v.Should().Be(10);
var v2 = await CachedCheck("bar", 20);
v2.Should().Be(20);
var v3 = await CachedCheck("baz", 30);
v3.Should().Be(30);
}
{
var v = await CachedCheck("foo", 10);
v.Should().Be(10);
var v2 = await CachedCheck("bar", 20);
v2.Should().Be(20);
var v3 = await CachedCheck("baz", 30);
v3.Should().Be(30);
}
{
var v = CachedCheck("foo", 10);
var v2 = CachedCheck("bar", 20);
var v3 = CachedCheck("baz", 30);
(await v).Should().Be(10);
(await v2).Should().Be(20);
(await v3).Should().Be(30);
}
{
var v = CachedCheck("foo", 10, true);
var v2 = CachedCheck("bar", 20, true);
var v3 = CachedCheck("baz", 30, true);
(await v).Should().Be(10);
(await v2).Should().Be(20);
(await v3).Should().Be(30);
}
});
static Dictionary<string, int> cacheDict = new Dictionary<string, int>();
async UniTask<int> CachedCheck(string cache, int value, bool yield = false)
{
if (!cacheDict.ContainsKey(cache))
{
await UniTask.Yield();
}
if (yield)
{
await UniTask.Yield();
}
if (cacheDict.TryGetValue(cache, out var v))
{
return v;
}
cacheDict.Add(cache, value);
return value;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 416e0e77b4408b0498792eb218ed2870
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,394 @@
using Cysharp.Threading.Tasks;
using Cysharp.Threading.Tasks.Linq;
using FluentAssertions;
using NUnit.Framework;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.TestTools;
namespace Cysharp.Threading.TasksTests
{
public class DelayTest
{
//[UnityTest]
//public IEnumerator DelayFrame() => UniTask.ToCoroutine(async () =>
//{
// for (int i = 1; i < 5; i++)
// {
// await UniTask.Yield(PlayerLoopTiming.PreUpdate);
// var frameCount = Time.frameCount;
// await UniTask.DelayFrame(i);
// Time.frameCount.Should().Be(frameCount + i);
// }
// for (int i = 1; i < 5; i++)
// {
// await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
// var frameCount = Time.frameCount;
// await UniTask.DelayFrame(i);
// Time.frameCount.Should().Be(frameCount + i);
// }
//});
//[UnityTest]
//public IEnumerator DelayFrameZero() => UniTask.ToCoroutine(async () =>
//{
// {
// await UniTask.Yield(PlayerLoopTiming.PreUpdate);
// var frameCount = Time.frameCount;
// await UniTask.DelayFrame(0);
// Time.frameCount.Should().Be(frameCount); // same frame
// }
// {
// await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
// var frameCount = Time.frameCount;
// await UniTask.DelayFrame(0);
// Time.frameCount.Should().Be(frameCount + 1); // next frame
// }
//});
//[UnityTest]
//public IEnumerator TimerFramePre() => UniTask.ToCoroutine(async () =>
//{
// await UniTask.Yield(PlayerLoopTiming.PreUpdate);
// var initialFrame = Time.frameCount;
// var xs = await UniTaskAsyncEnumerable.TimerFrame(2, 3).Take(5).Select(_ => Time.frameCount).ToArrayAsync();
// xs[0].Should().Be(initialFrame + 2);
// xs[1].Should().Be(initialFrame + 2 + (3 * 1));
// xs[2].Should().Be(initialFrame + 2 + (3 * 2));
// xs[3].Should().Be(initialFrame + 2 + (3 * 3));
// xs[4].Should().Be(initialFrame + 2 + (3 * 4));
//});
//[UnityTest]
//public IEnumerator TimerFramePost() => UniTask.ToCoroutine(async () =>
//{
// await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
// var initialFrame = Time.frameCount;
// var xs = await UniTaskAsyncEnumerable.TimerFrame(2, 3).Take(5).Select(_ => Time.frameCount).ToArrayAsync();
// xs[0].Should().Be(initialFrame + 2);
// xs[1].Should().Be(initialFrame + 2 + (3 * 1));
// xs[2].Should().Be(initialFrame + 2 + (3 * 2));
// xs[3].Should().Be(initialFrame + 2 + (3 * 3));
// xs[4].Should().Be(initialFrame + 2 + (3 * 4));
//});
//[UnityTest]
//public IEnumerator TimerFrameTest() => UniTask.ToCoroutine(async () =>
//{
// await UniTask.Yield(PlayerLoopTiming.PreUpdate);
// var initialFrame = Time.frameCount;
// var xs = await UniTaskAsyncEnumerable.TimerFrame(0, 0).Take(5).Select(_ => Time.frameCount).ToArrayAsync();
// xs[0].Should().Be(initialFrame);
// xs[1].Should().Be(initialFrame + 1);
// xs[2].Should().Be(initialFrame + 2);
// xs[3].Should().Be(initialFrame + 3);
// xs[4].Should().Be(initialFrame + 4);
//});
[UnityTest]
public IEnumerator TimerFrameSinglePre2() => UniTask.ToCoroutine(async () =>
{
{
var xs = await UniTaskAsyncEnumerable.TimerFrame(1).ToArrayAsync();
}
//Debug.Log("------------------");
//{
// var xs = await UniTaskAsyncEnumerable.TimerFrame(1).ToArrayAsync();
//}
});
//[UnityTest]
//public IEnumerator TimerFrameSinglePre2() => UniTask.ToCoroutine(async () =>
//{
// {
// var initialFrame = Time.frameCount;
// var xs = await new MyTimerFrame(0, null)/*.Select(_ => Time.frameCount)*/.ToArrayAsync();
// Debug.Log("OK 0 ------------------");
// }
// {
// var xs = await new MyTimerFrame(1, null)/*.Select(_ =>
// {
// var t = Time.frameCount;
// UnityEngine.Debug.Log("store frameCount:" + t);
// return t;
// })*/.ToArrayAsync();
// }
//});
//[UnityTest]
//public IEnumerator TimerFrameSinglePre() => UniTask.ToCoroutine(async () =>
//{
// {
// await UniTask.Yield(PlayerLoopTiming.PreUpdate);
// var initialFrame = Time.frameCount;
// var xs = await UniTaskAsyncEnumerable.Return(UniTask.Yield(PlayerLoopTiming.Update, CancellationToken.None))/*.Select(_ => Time.frameCount)*/.ToArrayAsync();
// xs[0].Should().Be(initialFrame);
// Debug.Log("OK 0 ------------------");
// }
// {
// await UniTask.Yield(PlayerLoopTiming.PreUpdate);
// var initialFrame = Time.frameCount;
// Debug.Log("initialFrame:" + initialFrame);
// var xs = await UniTaskAsyncEnumerable.Return(UniTask.Yield(PlayerLoopTiming.Update, CancellationToken.None))/*.Select(_ =>
// {
// var t = Time.frameCount;
// UnityEngine.Debug.Log("store frameCount:" + t);
// return t;
// })*/.ToArrayAsync();
// Debug.Log("xs len:" + xs.Length);
// Debug.Log("xs[0]:" + xs[0]);
// xs[0].Should().Be(initialFrame + 1);
// Debug.Log("OK 1");
// }
// {
// //await UniTask.Yield(PlayerLoopTiming.PreUpdate);
// var initialFrame = Time.frameCount;
// var xs = await UniTaskAsyncEnumerable.TimerFrame(2).Select(_ => Time.frameCount).ToArrayAsync();
// xs[0].Should().Be(initialFrame + 2);
// Debug.Log("OK 2");
// }
//});
//[UnityTest]
//public IEnumerator TimerFrameSinglePost() => UniTask.ToCoroutine(async () =>
//{
// {
// //await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
// //var initialFrame = Time.frameCount;
// //var xs = await UniTaskAsyncEnumerable.TimerFrame(0).Select(_ => Time.frameCount).ToArrayAsync();
// //xs[0].Should().Be(initialFrame);
// }
// {
// //await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
// var initialFrame = Time.frameCount;
// var xs = await UniTaskAsyncEnumerable.TimerFrame(1).Select(_ => Time.frameCount).ToArrayAsync();
// xs[0].Should().Be(initialFrame + 1);
// }
// {
// //await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
// var initialFrame = Time.frameCount;
// var xs = await UniTaskAsyncEnumerable.TimerFrame(2).Select(_ => Time.frameCount).ToArrayAsync();
// xs[0].Should().Be(initialFrame + 2);
// }
//});
//[UnityTest]
//public IEnumerator Timer() => UniTask.ToCoroutine(async () =>
//{
// await UniTask.Yield(PlayerLoopTiming.PreUpdate);
// {
// var initialSeconds = Time.realtimeSinceStartup;
// var xs = await UniTaskAsyncEnumerable.Timer(TimeSpan.FromSeconds(2)).Select(_ => Time.realtimeSinceStartup).ToArrayAsync();
// Mathf.Approximately(initialSeconds, xs[0]).Should().BeFalse();
// Debug.Log("Init:" + initialSeconds);
// Debug.Log("After:" + xs[0]);
// }
//});
}
public class DelayTest2
{
[UnityTest]
public IEnumerator TimerFrameSinglePre2() => UniTask.ToCoroutine(async () =>
{
{
var xs = await UniTaskAsyncEnumerable.TimerFrame(1).ToArrayAsync();
}
Debug.Log("------------------");
{
var xs = await UniTaskAsyncEnumerable.TimerFrame(1).ToArrayAsync();
}
});
}
public class ThreadRunner
{
Thread thread;
public void Start(IPlayerLoopItem runner)
{
thread = new Thread(() =>
{
Thread.Sleep(30);
while (runner.MoveNext())
{
Thread.Sleep(30);
}
});
thread.Start();
}
}
internal class MyTimerFrame : IUniTaskAsyncEnumerable<AsyncUnit>
{
//readonly PlayerLoopTiming updateTiming;
readonly int dueTimeFrameCount;
readonly int? periodFrameCount;
public MyTimerFrame(int dueTimeFrameCount, int? periodFrameCount)
{
//this.updateTiming = updateTiming;
this.dueTimeFrameCount = dueTimeFrameCount;
this.periodFrameCount = periodFrameCount;
}
public IUniTaskAsyncEnumerator<AsyncUnit> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new _TimerFrame(dueTimeFrameCount, periodFrameCount, cancellationToken);
}
class _TimerFrame : MoveNextSource, IUniTaskAsyncEnumerator<AsyncUnit>, IPlayerLoopItem
{
readonly int dueTimeFrameCount;
readonly int? periodFrameCount;
CancellationToken cancellationToken;
int initialFrame;
int currentFrame;
bool dueTimePhase;
bool completed;
bool disposed;
ThreadRunner runner;
public _TimerFrame(int dueTimeFrameCount, int? periodFrameCount, CancellationToken cancellationToken)
{
if (dueTimeFrameCount <= 0) dueTimeFrameCount = 0;
if (periodFrameCount != null)
{
if (periodFrameCount <= 0) periodFrameCount = 1;
}
//this.initialFrame = Time.frameCount;
this.dueTimePhase = true;
this.dueTimeFrameCount = dueTimeFrameCount;
this.periodFrameCount = periodFrameCount;
//TaskTracker.TrackActiveTask(this, 2);
//PlayerLoopHelper.AddAction(updateTiming, this);
runner = new ThreadRunner();
runner.Start(this);
}
public AsyncUnit Current => default;
public UniTask<bool> MoveNextAsync()
{
// return false instead of throw
if (disposed || cancellationToken.IsCancellationRequested || completed) return default;
// reset value here.
this.currentFrame = 0;
completionSource.Reset();
return new UniTask<bool>(this, completionSource.Version);
}
public UniTask DisposeAsync()
{
if (!disposed)
{
disposed = true;
TaskTracker.RemoveTracking(this);
}
return default;
}
public bool MoveNext()
{
UnityEngine.Debug.Log("Called MoveNext");
if (disposed || cancellationToken.IsCancellationRequested)
{
UnityEngine.Debug.Log("Disposing");
completionSource.TrySetResult(false);
return false;
}
if (dueTimePhase)
{
UnityEngine.Debug.Log("In DueTime Phase");
if (currentFrame == 0)
{
if (dueTimeFrameCount == 0)
{
dueTimePhase = false;
completionSource.TrySetResult(true);
return true;
}
// skip in initial frame.
/*
UnityEngine.Debug.Log("(Init, frameConut)" + (initialFrame, Time.frameCount));
if (initialFrame == Time.frameCount)
{
UnityEngine.Debug.Log("Skip Here");
return true;
}
*/
}
UnityEngine.Debug.Log("Which Go?");
if (++currentFrame >= dueTimeFrameCount)
{
UnityEngine.Debug.Log("END Go?");
dueTimePhase = false;
completionSource.TrySetResult(true);
}
else
{
UnityEngine.Debug.Log("NG Go?");
}
}
else
{
if (periodFrameCount == null)
{
UnityEngine.Debug.Log("PERIOD");
completed = true;
completionSource.TrySetResult(false);
return false;
}
if (++currentFrame >= periodFrameCount)
{
completionSource.TrySetResult(true);
}
}
return true;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1376b93d9e1083a4a9b4081e08f3a7b7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,400 +1,400 @@
#if !(UNITY_4_5 || UNITY_4_6 || UNITY_4_7 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2) //#if !(UNITY_4_5 || UNITY_4_6 || UNITY_4_7 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2)
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member //#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using UnityEngine; //using UnityEngine;
using System; //using System;
using System.Collections; //using System.Collections;
using System.Collections.Generic; //using System.Collections.Generic;
using System.Linq; //using System.Linq;
using System.Text; //using System.Text;
using UnityEngine.UI; //using UnityEngine.UI;
using UnityEngine.Scripting; //using UnityEngine.Scripting;
using Cysharp.Threading.Tasks; //using Cysharp.Threading.Tasks;
using UnityEngine.SceneManagement; //using UnityEngine.SceneManagement;
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6)) //#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
using System.Threading.Tasks; //using System.Threading.Tasks;
#endif //#endif
using UnityEngine.Networking; //using UnityEngine.Networking;
#if !UNITY_2019_3_OR_NEWER //#if !UNITY_2019_3_OR_NEWER
using UnityEngine.Experimental.LowLevel; //using UnityEngine.Experimental.LowLevel;
#else //#else
using UnityEngine.LowLevel; //using UnityEngine.LowLevel;
#endif //#endif
#if !UNITY_WSA //#if !UNITY_WSA
using Unity.Jobs; //using Unity.Jobs;
#endif //#endif
using Unity.Collections; //using Unity.Collections;
using System.Threading; //using System.Threading;
using NUnit.Framework; //using NUnit.Framework;
using UnityEngine.TestTools; //using UnityEngine.TestTools;
using FluentAssertions; //using FluentAssertions;
namespace Cysharp.Threading.TasksTests //namespace Cysharp.Threading.TasksTests
{ //{
public class AsyncTest // public class AsyncTest
{ // {
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6)) //#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
#if !UNITY_WSA //#if !UNITY_WSA
public struct MyJob : IJob // public struct MyJob : IJob
{ // {
public int loopCount; // public int loopCount;
public NativeArray<int> inOut; // public NativeArray<int> inOut;
public int result; // public int result;
public void Execute() // public void Execute()
{ // {
result = 0; // result = 0;
for (int i = 0; i < loopCount; i++) // for (int i = 0; i < loopCount; i++)
{ // {
result++; // result++;
} // }
inOut[0] = result; // inOut[0] = result;
} // }
} // }
[UnityTest] // [UnityTest]
public IEnumerator DelayAnd() => UniTask.ToCoroutine(async () => // public IEnumerator DelayAnd() => UniTask.ToCoroutine(async () =>
{ // {
await UniTask.Yield(PlayerLoopTiming.PostLateUpdate); // await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
var time = Time.realtimeSinceStartup; // var time = Time.realtimeSinceStartup;
Time.timeScale = 0.5f; // Time.timeScale = 0.5f;
try // try
{ // {
await UniTask.Delay(TimeSpan.FromSeconds(3)); // await UniTask.Delay(TimeSpan.FromSeconds(3));
var elapsed = Time.realtimeSinceStartup - time; // var elapsed = Time.realtimeSinceStartup - time;
((int)Math.Round(TimeSpan.FromSeconds(elapsed).TotalSeconds, MidpointRounding.ToEven)).Should().Be(6); // ((int)Math.Round(TimeSpan.FromSeconds(elapsed).TotalSeconds, MidpointRounding.ToEven)).Should().Be(6);
} // }
finally // finally
{ // {
Time.timeScale = 1.0f; // Time.timeScale = 1.0f;
} // }
}); // });
[UnityTest] // [UnityTest]
public IEnumerator DelayIgnore() => UniTask.ToCoroutine(async () => // public IEnumerator DelayIgnore() => UniTask.ToCoroutine(async () =>
{ // {
var time = Time.realtimeSinceStartup; // var time = Time.realtimeSinceStartup;
Time.timeScale = 0.5f; // Time.timeScale = 0.5f;
try // try
{ // {
await UniTask.Delay(TimeSpan.FromSeconds(3), ignoreTimeScale: true); // await UniTask.Delay(TimeSpan.FromSeconds(3), ignoreTimeScale: true);
var elapsed = Time.realtimeSinceStartup - time; // var elapsed = Time.realtimeSinceStartup - time;
((int)Math.Round(TimeSpan.FromSeconds(elapsed).TotalSeconds, MidpointRounding.ToEven)).Should().Be(3); // ((int)Math.Round(TimeSpan.FromSeconds(elapsed).TotalSeconds, MidpointRounding.ToEven)).Should().Be(3);
} // }
finally // finally
{ // {
Time.timeScale = 1.0f; // Time.timeScale = 1.0f;
} // }
}); // });
[UnityTest] // [UnityTest]
public IEnumerator WhenAll() => UniTask.ToCoroutine(async () => // public IEnumerator WhenAll() => UniTask.ToCoroutine(async () =>
{ // {
var a = UniTask.FromResult(999); // var a = UniTask.FromResult(999);
var b = UniTask.Yield(PlayerLoopTiming.Update, CancellationToken.None).AsAsyncUnitUniTask(); // var b = UniTask.Yield(PlayerLoopTiming.Update, CancellationToken.None).AsAsyncUnitUniTask();
var c = UniTask.DelayFrame(99).AsAsyncUnitUniTask(); // var c = UniTask.DelayFrame(99).AsAsyncUnitUniTask();
var (a2, b2, c2) = await UniTask.WhenAll(a, b, c); // var (a2, b2, c2) = await UniTask.WhenAll(a, b, c);
a2.Should().Be(999); // a2.Should().Be(999);
b2.Should().Be(AsyncUnit.Default); // b2.Should().Be(AsyncUnit.Default);
c2.Should().Be(AsyncUnit.Default); // c2.Should().Be(AsyncUnit.Default);
}); // });
[UnityTest] // [UnityTest]
public IEnumerator WhenAny() => UniTask.ToCoroutine(async () => // public IEnumerator WhenAny() => UniTask.ToCoroutine(async () =>
{ // {
var a = UniTask.FromResult(999); // var a = UniTask.FromResult(999);
var b = UniTask.Yield(PlayerLoopTiming.Update, CancellationToken.None).AsAsyncUnitUniTask(); // var b = UniTask.Yield(PlayerLoopTiming.Update, CancellationToken.None).AsAsyncUnitUniTask();
var c = UniTask.DelayFrame(99).AsAsyncUnitUniTask(); // var c = UniTask.DelayFrame(99).AsAsyncUnitUniTask();
var (win, a2, b2, c2) = await UniTask.WhenAny(a, b, c); // var (win, a2, b2, c2) = await UniTask.WhenAny(a, b, c);
win.Should().Be(0); // win.Should().Be(0);
a2.Should().Be(999); // a2.Should().Be(999);
}); // });
[UnityTest] // [UnityTest]
public IEnumerator BothEnumeratorCheck() => UniTask.ToCoroutine(async () => // public IEnumerator BothEnumeratorCheck() => UniTask.ToCoroutine(async () =>
{ // {
await ToaruCoroutineEnumerator(); // wait 5 frame:) // await ToaruCoroutineEnumerator(); // wait 5 frame:)
}); // });
[UnityTest] // [UnityTest]
public IEnumerator JobSystem() => UniTask.ToCoroutine(async () => // public IEnumerator JobSystem() => UniTask.ToCoroutine(async () =>
{ // {
var job = new MyJob() { loopCount = 999, inOut = new NativeArray<int>(1, Allocator.TempJob) }; // var job = new MyJob() { loopCount = 999, inOut = new NativeArray<int>(1, Allocator.TempJob) };
JobHandle.ScheduleBatchedJobs(); // JobHandle.ScheduleBatchedJobs();
await job.Schedule(); // await job.Schedule();
job.inOut[0].Should().Be(999); // job.inOut[0].Should().Be(999);
job.inOut.Dispose(); // job.inOut.Dispose();
}); // });
class MyMyClass // class MyMyClass
{ // {
public int MyProperty { get; set; } // public int MyProperty { get; set; }
} // }
[UnityTest] // [UnityTest]
public IEnumerator WaitUntil() => UniTask.ToCoroutine(async () => // public IEnumerator WaitUntil() => UniTask.ToCoroutine(async () =>
{ // {
bool t = false; // bool t = false;
await UniTask.Yield(PlayerLoopTiming.PostLateUpdate); // await UniTask.Yield(PlayerLoopTiming.PostLateUpdate);
UniTask.DelayFrame(10,PlayerLoopTiming.PostLateUpdate).ContinueWith(() => t = true).Forget(); // UniTask.DelayFrame(10,PlayerLoopTiming.PostLateUpdate).ContinueWith(() => t = true).Forget();
var startFrame = Time.frameCount; // var startFrame = Time.frameCount;
await UniTask.WaitUntil(() => t, PlayerLoopTiming.EarlyUpdate); // await UniTask.WaitUntil(() => t, PlayerLoopTiming.EarlyUpdate);
var diff = Time.frameCount - startFrame; // var diff = Time.frameCount - startFrame;
diff.Should().Be(11); // diff.Should().Be(11);
}); // });
[UnityTest] // [UnityTest]
public IEnumerator WaitWhile() => UniTask.ToCoroutine(async () => // public IEnumerator WaitWhile() => UniTask.ToCoroutine(async () =>
{ // {
bool t = true; // bool t = true;
UniTask.DelayFrame(10, PlayerLoopTiming.PostLateUpdate).ContinueWith(() => t = false).Forget(); // UniTask.DelayFrame(10, PlayerLoopTiming.PostLateUpdate).ContinueWith(() => t = false).Forget();
var startFrame = Time.frameCount; // var startFrame = Time.frameCount;
await UniTask.WaitWhile(() => t, PlayerLoopTiming.EarlyUpdate); // await UniTask.WaitWhile(() => t, PlayerLoopTiming.EarlyUpdate);
var diff = Time.frameCount - startFrame; // var diff = Time.frameCount - startFrame;
diff.Should().Be(11); // diff.Should().Be(11);
}); // });
[UnityTest] // [UnityTest]
public IEnumerator WaitUntilValueChanged() => UniTask.ToCoroutine(async () => // public IEnumerator WaitUntilValueChanged() => UniTask.ToCoroutine(async () =>
{ // {
var v = new MyMyClass { MyProperty = 99 }; // var v = new MyMyClass { MyProperty = 99 };
UniTask.DelayFrame(10, PlayerLoopTiming.PostLateUpdate).ContinueWith(() => v.MyProperty = 1000).Forget(); // UniTask.DelayFrame(10, PlayerLoopTiming.PostLateUpdate).ContinueWith(() => v.MyProperty = 1000).Forget();
var startFrame = Time.frameCount; // var startFrame = Time.frameCount;
await UniTask.WaitUntilValueChanged(v, x => x.MyProperty, PlayerLoopTiming.EarlyUpdate); // await UniTask.WaitUntilValueChanged(v, x => x.MyProperty, PlayerLoopTiming.EarlyUpdate);
var diff = Time.frameCount - startFrame; // var diff = Time.frameCount - startFrame;
diff.Should().Be(11); // diff.Should().Be(11);
}); // });
[UnityTest] // [UnityTest]
public IEnumerator SwitchTo() => UniTask.ToCoroutine(async () => // public IEnumerator SwitchTo() => UniTask.ToCoroutine(async () =>
{ // {
await UniTask.Yield(); // await UniTask.Yield();
var currentThreadId = Thread.CurrentThread.ManagedThreadId; // var currentThreadId = Thread.CurrentThread.ManagedThreadId;
await UniTask.SwitchToThreadPool(); // await UniTask.SwitchToThreadPool();
//await UniTask.SwitchToThreadPool(); // //await UniTask.SwitchToThreadPool();
//await UniTask.SwitchToThreadPool(); // //await UniTask.SwitchToThreadPool();
var switchedThreadId = Thread.CurrentThread.ManagedThreadId; // var switchedThreadId = Thread.CurrentThread.ManagedThreadId;
currentThreadId.Should().NotBe(switchedThreadId); // currentThreadId.Should().NotBe(switchedThreadId);
await UniTask.Yield(); // await UniTask.Yield();
var switchedThreadId2 = Thread.CurrentThread.ManagedThreadId; // var switchedThreadId2 = Thread.CurrentThread.ManagedThreadId;
currentThreadId.Should().Be(switchedThreadId2); // currentThreadId.Should().Be(switchedThreadId2);
}); // });
//[UnityTest] // //[UnityTest]
//public IEnumerator ObservableConversion() => UniTask.ToCoroutine(async () => // //public IEnumerator ObservableConversion() => UniTask.ToCoroutine(async () =>
//{ // //{
// var v = await Observable.Range(1, 10).ToUniTask(); // // var v = await Observable.Range(1, 10).ToUniTask();
// v.Is(10); // // v.Is(10);
// v = await Observable.Range(1, 10).ToUniTask(useFirstValue: true); // // v = await Observable.Range(1, 10).ToUniTask(useFirstValue: true);
// v.Is(1); // // v.Is(1);
// v = await UniTask.DelayFrame(10).ToObservable().ToTask(); // // v = await UniTask.DelayFrame(10).ToObservable().ToTask();
// v.Is(10); // // v.Is(10);
// v = await UniTask.FromResult(99).ToObservable(); // // v = await UniTask.FromResult(99).ToObservable();
// v.Is(99); // // v.Is(99);
//}); // //});
//[UnityTest] // //[UnityTest]
//public IEnumerator AwaitableReactiveProperty() => UniTask.ToCoroutine(async () => // //public IEnumerator AwaitableReactiveProperty() => UniTask.ToCoroutine(async () =>
//{ // //{
// var rp1 = new ReactiveProperty<int>(99); // // var rp1 = new ReactiveProperty<int>(99);
// UniTask.DelayFrame(100).ContinueWith(x => rp1.Value = x).Forget(); // // UniTask.DelayFrame(100).ContinueWith(x => rp1.Value = x).Forget();
// await rp1; // // await rp1;
// rp1.Value.Is(100); // // rp1.Value.Is(100);
// // var delay2 = UniTask.DelayFrame(10); // // // var delay2 = UniTask.DelayFrame(10);
// // var (a, b ) = await UniTask.WhenAll(rp1.WaitUntilValueChangedAsync(), delay2); // // // var (a, b ) = await UniTask.WhenAll(rp1.WaitUntilValueChangedAsync(), delay2);
//}); // //});
//[UnityTest] // //[UnityTest]
//public IEnumerator AwaitableReactiveCommand() => UniTask.ToCoroutine(async () => // //public IEnumerator AwaitableReactiveCommand() => UniTask.ToCoroutine(async () =>
//{ // //{
// var rc = new ReactiveCommand<int>(); // // var rc = new ReactiveCommand<int>();
// UniTask.DelayFrame(100).ContinueWith(x => rc.Execute(x)).Forget(); // // UniTask.DelayFrame(100).ContinueWith(x => rc.Execute(x)).Forget();
// var v = await rc; // // var v = await rc;
// v.Is(100); // // v.Is(100);
//}); // //});
[UnityTest] // [UnityTest]
public IEnumerator ExceptionlessCancellation() => UniTask.ToCoroutine(async () => // public IEnumerator ExceptionlessCancellation() => UniTask.ToCoroutine(async () =>
{ // {
var cts = new CancellationTokenSource(); // var cts = new CancellationTokenSource();
UniTask.DelayFrame(10).ContinueWith(() => cts.Cancel()).Forget(); // UniTask.DelayFrame(10).ContinueWith(() => cts.Cancel()).Forget();
var first = Time.frameCount; // var first = Time.frameCount;
var canceled = await UniTask.DelayFrame(100, cancellationToken: cts.Token).SuppressCancellationThrow(); // var canceled = await UniTask.DelayFrame(100, cancellationToken: cts.Token).SuppressCancellationThrow();
(Time.frameCount - first).Should().Be(11); // 10 frame canceled // (Time.frameCount - first).Should().Be(11); // 10 frame canceled
canceled.Should().Be(true); // canceled.Should().Be(true);
}); // });
[UnityTest] // [UnityTest]
public IEnumerator ExceptionCancellation() => UniTask.ToCoroutine(async () => // public IEnumerator ExceptionCancellation() => UniTask.ToCoroutine(async () =>
{ // {
var cts = new CancellationTokenSource(); // var cts = new CancellationTokenSource();
UniTask.DelayFrame(10).ContinueWith(() => cts.Cancel()).Forget(); // UniTask.DelayFrame(10).ContinueWith(() => cts.Cancel()).Forget();
bool occur = false; // bool occur = false;
try // try
{ // {
await UniTask.DelayFrame(100, cancellationToken: cts.Token); // await UniTask.DelayFrame(100, cancellationToken: cts.Token);
} // }
catch (OperationCanceledException) // catch (OperationCanceledException)
{ // {
occur = true; // occur = true;
} // }
occur.Should().BeTrue(); // occur.Should().BeTrue();
}); // });
IEnumerator ToaruCoroutineEnumerator() // IEnumerator ToaruCoroutineEnumerator()
{ // {
yield return null; // yield return null;
yield return null; // yield return null;
yield return null; // yield return null;
yield return null; // yield return null;
yield return null; // yield return null;
} // }
[UnityTest] // [UnityTest]
public IEnumerator ExceptionUnobserved1() => UniTask.ToCoroutine(async () => // public IEnumerator ExceptionUnobserved1() => UniTask.ToCoroutine(async () =>
{ // {
bool calledEx = false; // bool calledEx = false;
Action<Exception> action = exx => // Action<Exception> action = exx =>
{ // {
calledEx = true; // calledEx = true;
exx.Message.Should().Be("MyException"); // exx.Message.Should().Be("MyException");
}; // };
UniTaskScheduler.UnobservedTaskException += action; // UniTaskScheduler.UnobservedTaskException += action;
var ex = InException1(); // var ex = InException1();
ex = default(UniTask); // ex = default(UniTask);
await UniTask.DelayFrame(3); // await UniTask.DelayFrame(3);
GC.Collect(); // GC.Collect();
GC.WaitForPendingFinalizers(); // GC.WaitForPendingFinalizers();
GC.Collect(); // GC.Collect();
await UniTask.DelayFrame(1); // await UniTask.DelayFrame(1);
calledEx.Should().BeTrue(); // calledEx.Should().BeTrue();
UniTaskScheduler.UnobservedTaskException -= action; // UniTaskScheduler.UnobservedTaskException -= action;
}); // });
[UnityTest] // [UnityTest]
public IEnumerator ExceptionUnobserved2() => UniTask.ToCoroutine(async () => // public IEnumerator ExceptionUnobserved2() => UniTask.ToCoroutine(async () =>
{ // {
bool calledEx = false; // bool calledEx = false;
Action<Exception> action = exx => // Action<Exception> action = exx =>
{ // {
calledEx = true; // calledEx = true;
exx.Message.Should().Be("MyException"); // exx.Message.Should().Be("MyException");
}; // };
UniTaskScheduler.UnobservedTaskException += action; // UniTaskScheduler.UnobservedTaskException += action;
var ex = InException2(); // var ex = InException2();
ex = default(UniTask<int>); // ex = default(UniTask<int>);
await UniTask.DelayFrame(3); // await UniTask.DelayFrame(3);
GC.Collect(); // GC.Collect();
GC.WaitForPendingFinalizers(); // GC.WaitForPendingFinalizers();
GC.Collect(); // GC.Collect();
await UniTask.DelayFrame(1); // await UniTask.DelayFrame(1);
calledEx.Should().BeTrue(); // calledEx.Should().BeTrue();
UniTaskScheduler.UnobservedTaskException -= action; // UniTaskScheduler.UnobservedTaskException -= action;
}); // });
async UniTask InException1() // async UniTask InException1()
{ // {
await UniTask.Yield(); // await UniTask.Yield();
throw new Exception("MyException"); // throw new Exception("MyException");
} // }
async UniTask<int> InException2() // async UniTask<int> InException2()
{ // {
await UniTask.Yield(); // await UniTask.Yield();
throw new Exception("MyException"); // throw new Exception("MyException");
} // }
[UnityTest] // [UnityTest]
public IEnumerator NestedEnumerator() => UniTask.ToCoroutine(async () => // public IEnumerator NestedEnumerator() => UniTask.ToCoroutine(async () =>
{ // {
var time = Time.realtimeSinceStartup; // var time = Time.realtimeSinceStartup;
await ParentCoroutineEnumerator(); // await ParentCoroutineEnumerator();
var elapsed = Time.realtimeSinceStartup - time; // var elapsed = Time.realtimeSinceStartup - time;
((int)Math.Round(TimeSpan.FromSeconds(elapsed).TotalSeconds, MidpointRounding.ToEven)).Should().Be(3); // ((int)Math.Round(TimeSpan.FromSeconds(elapsed).TotalSeconds, MidpointRounding.ToEven)).Should().Be(3);
}); // });
IEnumerator ParentCoroutineEnumerator() // IEnumerator ParentCoroutineEnumerator()
{ // {
yield return ChildCoroutineEnumerator(); // yield return ChildCoroutineEnumerator();
} // }
IEnumerator ChildCoroutineEnumerator() // IEnumerator ChildCoroutineEnumerator()
{ // {
yield return new WaitForSeconds(3); // yield return new WaitForSeconds(3);
} // }
#endif //#endif
#endif //#endif
} // }
} //}
#endif //#endif

View File

@ -1,95 +1,95 @@
#if !(UNITY_4_5 || UNITY_4_6 || UNITY_4_7 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2) //#if !(UNITY_4_5 || UNITY_4_6 || UNITY_4_7 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2)
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member //#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using UnityEngine; //using UnityEngine;
using System; //using System;
using System.Collections; //using System.Collections;
using System.Collections.Generic; //using System.Collections.Generic;
using System.Linq; //using System.Linq;
using System.Text; //using System.Text;
using UnityEngine.UI; //using UnityEngine.UI;
using UnityEngine.Scripting; //using UnityEngine.Scripting;
using Cysharp.Threading.Tasks; //using Cysharp.Threading.Tasks;
using UnityEngine.SceneManagement; //using UnityEngine.SceneManagement;
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6)) //#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
using System.Threading.Tasks; //using System.Threading.Tasks;
#endif //#endif
using UnityEngine.Networking; //using UnityEngine.Networking;
#if !UNITY_2019_3_OR_NEWER //#if !UNITY_2019_3_OR_NEWER
using UnityEngine.Experimental.LowLevel; //using UnityEngine.Experimental.LowLevel;
#else //#else
using UnityEngine.LowLevel; //using UnityEngine.LowLevel;
#endif //#endif
#if !UNITY_WSA //#if !UNITY_WSA
using Unity.Jobs; //using Unity.Jobs;
#endif //#endif
using Unity.Collections; //using Unity.Collections;
using System.Threading; //using System.Threading;
using NUnit.Framework; //using NUnit.Framework;
using UnityEngine.TestTools; //using UnityEngine.TestTools;
using FluentAssertions; //using FluentAssertions;
namespace Cysharp.Threading.TasksTests //namespace Cysharp.Threading.TasksTests
{ //{
public class RunTest // public class RunTest
{ // {
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6)) //#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
#if !UNITY_WSA //#if !UNITY_WSA
//[UnityTest] // //[UnityTest]
//public IEnumerator RunThread() => UniTask.ToCoroutine(async () => // //public IEnumerator RunThread() => UniTask.ToCoroutine(async () =>
//{ // //{
// var main = Thread.CurrentThread.ManagedThreadId; // // var main = Thread.CurrentThread.ManagedThreadId;
// var v = await UniTask.Run(() => { return System.Threading.Thread.CurrentThread.ManagedThreadId; }, false); // // var v = await UniTask.Run(() => { return System.Threading.Thread.CurrentThread.ManagedThreadId; }, false);
// UnityEngine.Debug.Log("Ret Value is:" + v); // // UnityEngine.Debug.Log("Ret Value is:" + v);
// UnityEngine.Debug.Log("Run Here and id:" + System.Threading.Thread.CurrentThread.ManagedThreadId); // // UnityEngine.Debug.Log("Run Here and id:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
// //v.Should().Be(3); // // //v.Should().Be(3);
// main.Should().NotBe(Thread.CurrentThread.ManagedThreadId); // // main.Should().NotBe(Thread.CurrentThread.ManagedThreadId);
//}); // //});
[UnityTest] // [UnityTest]
public IEnumerator RunThreadConfigure() => UniTask.ToCoroutine(async () => // public IEnumerator RunThreadConfigure() => UniTask.ToCoroutine(async () =>
{ // {
var main = Thread.CurrentThread.ManagedThreadId; // var main = Thread.CurrentThread.ManagedThreadId;
var v = await UniTask.Run(() => 3, true); // var v = await UniTask.Run(() => 3, true);
v.Should().Be(3); // v.Should().Be(3);
main.Should().Be(Thread.CurrentThread.ManagedThreadId); // main.Should().Be(Thread.CurrentThread.ManagedThreadId);
}); // });
//[UnityTest] // //[UnityTest]
//public IEnumerator RunThreadException() => UniTask.ToCoroutine(async () => // //public IEnumerator RunThreadException() => UniTask.ToCoroutine(async () =>
//{ // //{
// var main = Thread.CurrentThread.ManagedThreadId; // // var main = Thread.CurrentThread.ManagedThreadId;
// try // // try
// { // // {
// await UniTask.Run<int>(() => throw new Exception(), false); // // await UniTask.Run<int>(() => throw new Exception(), false);
// } // // }
// catch // // catch
// { // // {
// main.Should().NotBe(Thread.CurrentThread.ManagedThreadId); // // main.Should().NotBe(Thread.CurrentThread.ManagedThreadId);
// } // // }
//}); // //});
[UnityTest] // [UnityTest]
public IEnumerator RunThreadExceptionConfigure() => UniTask.ToCoroutine(async () => // public IEnumerator RunThreadExceptionConfigure() => UniTask.ToCoroutine(async () =>
{ // {
var main = Thread.CurrentThread.ManagedThreadId; // var main = Thread.CurrentThread.ManagedThreadId;
try // try
{ // {
await UniTask.Run<int>(() => throw new Exception(), true); // await UniTask.Run<int>(() => throw new Exception(), true);
} // }
catch // catch
{ // {
main.Should().Be(Thread.CurrentThread.ManagedThreadId); // main.Should().Be(Thread.CurrentThread.ManagedThreadId);
} // }
}); // });
#endif //#endif
#endif //#endif
} // }
} //}
#endif //#endif

View File

@ -1,43 +1,43 @@
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6)) //#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member //#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using UnityEngine; //using UnityEngine;
using System; //using System;
using System.Collections; //using System.Collections;
using System.Collections.Generic; //using System.Collections.Generic;
using System.Linq; //using System.Linq;
using System.Text; //using System.Text;
using UnityEngine.UI; //using UnityEngine.UI;
using UnityEngine.Scripting; //using UnityEngine.Scripting;
using Cysharp.Threading.Tasks; //using Cysharp.Threading.Tasks;
using Unity.Collections; //using Unity.Collections;
using System.Threading; //using System.Threading;
using NUnit.Framework; //using NUnit.Framework;
using UnityEngine.TestTools; //using UnityEngine.TestTools;
using FluentAssertions; //using FluentAssertions;
namespace Cysharp.Threading.TasksTests //namespace Cysharp.Threading.TasksTests
{ //{
public class WhenAnyTest // public class WhenAnyTest
{ // {
[UnityTest] // [UnityTest]
public IEnumerator WhenAnyCanceled() => UniTask.ToCoroutine(async () => // public IEnumerator WhenAnyCanceled() => UniTask.ToCoroutine(async () =>
{ // {
var cts = new CancellationTokenSource(); // var cts = new CancellationTokenSource();
var successDelayTask = UniTask.Delay(TimeSpan.FromSeconds(1)); // var successDelayTask = UniTask.Delay(TimeSpan.FromSeconds(1));
var cancelTask = UniTask.Delay(TimeSpan.FromSeconds(1), cancellationToken: cts.Token); // var cancelTask = UniTask.Delay(TimeSpan.FromSeconds(1), cancellationToken: cts.Token);
cts.CancelAfterSlim(200); // cts.CancelAfterSlim(200);
try // try
{ // {
var r = await UniTask.WhenAny(new[] { successDelayTask, cancelTask }); // var r = await UniTask.WhenAny(new[] { successDelayTask, cancelTask });
} // }
catch (Exception ex) // catch (Exception ex)
{ // {
ex.Should().BeAssignableTo<OperationCanceledException>(); // ex.Should().BeAssignableTo<OperationCanceledException>();
} // }
}); // });
} // }
} //}
#endif //#endif

View File

@ -6,13 +6,20 @@ using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.TestTools; using UnityEngine.TestTools;
namespace Cysharp.Threading.TasksTests namespace Cysharp.Threading.TasksTests
{ {
public class Preserve public class Preserve
{ {
public Preserve()
{
// TaskPool.SetMaxPoolSize(0);
}
[UnityTest] [UnityTest]
public IEnumerator AwaitTwice() => UniTask.ToCoroutine(async () => public IEnumerator AwaitTwice() => UniTask.ToCoroutine(async () =>
{ {
@ -33,12 +40,17 @@ namespace Cysharp.Threading.TasksTests
[UnityTest] [UnityTest]
public IEnumerator PreserveAllowTwice() => UniTask.ToCoroutine(async () => public IEnumerator PreserveAllowTwice() => UniTask.ToCoroutine(async () =>
{ {
await UniTask.Yield(PlayerLoopTiming.Update);
var delay = UniTask.DelayFrame(5, PlayerLoopTiming.PostLateUpdate).Preserve(); var delay = UniTask.DelayFrame(5, PlayerLoopTiming.PostLateUpdate).Preserve();
var before = UnityEngine.Time.frameCount;
var before = UnityEngine.Time.frameCount; // 0
await delay; await delay;
var afterOne = UnityEngine.Time.frameCount; var afterOne = UnityEngine.Time.frameCount; // 5
await delay; await delay;
var afterTwo = UnityEngine.Time.frameCount; var afterTwo = UnityEngine.Time.frameCount; // 5
(afterOne - before).Should().Be(5); (afterOne - before).Should().Be(5);
afterOne.Should().Be(afterTwo); afterOne.Should().Be(afterTwo);

View File

@ -5,7 +5,8 @@
"UnityEditor.TestRunner", "UnityEditor.TestRunner",
"UniTask", "UniTask",
"Unity.ResourceManager", "Unity.ResourceManager",
"DOTween.Modules" "DOTween.Modules",
"UniTask.Linq"
], ],
"includePlatforms": [], "includePlatforms": [],
"excludePlatforms": [], "excludePlatforms": [],