fix IEnumerator.ToUniTask, does not work correctly when coroutine complete immediately

master
neuecc 2020-09-15 06:35:22 +09:00
parent 85fb08552e
commit e0d8410b62
2 changed files with 63 additions and 1 deletions

View File

@ -46,6 +46,8 @@ namespace Cysharp.Threading.Tasks
IEnumerator innerEnumerator; IEnumerator innerEnumerator;
CancellationToken cancellationToken; CancellationToken cancellationToken;
int initialFrame; int initialFrame;
bool loopRunning;
bool calledGetResult;
UniTaskCompletionSourceCore<object> core; UniTaskCompletionSourceCore<object> core;
@ -68,6 +70,8 @@ namespace Cysharp.Threading.Tasks
result.innerEnumerator = ConsumeEnumerator(innerEnumerator); result.innerEnumerator = ConsumeEnumerator(innerEnumerator);
result.cancellationToken = cancellationToken; result.cancellationToken = cancellationToken;
result.loopRunning = true;
result.calledGetResult = false;
result.initialFrame = -1; result.initialFrame = -1;
PlayerLoopHelper.AddAction(timing, result); PlayerLoopHelper.AddAction(timing, result);
@ -82,11 +86,15 @@ namespace Cysharp.Threading.Tasks
{ {
try try
{ {
calledGetResult = true;
core.GetResult(token); core.GetResult(token);
} }
finally finally
{ {
TryReturn(); if (!loopRunning)
{
TryReturn();
}
} }
} }
@ -107,8 +115,21 @@ namespace Cysharp.Threading.Tasks
public bool MoveNext() public bool MoveNext()
{ {
if (calledGetResult)
{
loopRunning = false;
TryReturn();
return false;
}
if (innerEnumerator == null) // invalid status, returned but loop running?
{
return false;
}
if (cancellationToken.IsCancellationRequested) if (cancellationToken.IsCancellationRequested)
{ {
loopRunning = false;
core.TrySetCanceled(cancellationToken); core.TrySetCanceled(cancellationToken);
return false; return false;
} }
@ -135,10 +156,12 @@ namespace Cysharp.Threading.Tasks
} }
catch (Exception ex) catch (Exception ex)
{ {
loopRunning = false;
core.TrySetException(ex); core.TrySetException(ex);
return false; return false;
} }
loopRunning = false;
core.TrySetResult(null); core.TrySetResult(null);
return false; return false;
} }

View File

@ -96,6 +96,45 @@ namespace Cysharp.Threading.TasksTests
// l[1].Item2.Should().NotBe(currentFrame); // l[1].Item2.Should().NotBe(currentFrame);
//} //}
[UnityTest]
public IEnumerator ImmediateRunTest() => UniTask.ToCoroutine(async () =>
{
var l = new List<int>();
var x1 = Immediate(l);
var x2 = Immediate(l);
var x3 = DelayOne(l);
var t1 = x1.ToUniTask();
CollectionAssert.AreEqual(l, new[] { 1, 2, 3 });
await t1;
var t2 = x2.ToUniTask();
CollectionAssert.AreEqual(l, new[] { 1, 2, 3, 1, 2, 3 });
var t3 = x3.ToUniTask();
CollectionAssert.AreEqual(l, new[] { 1, 2, 3, 1, 2, 3, 10 });
await UniTask.WhenAll(t2, t3);
CollectionAssert.AreEqual(l, new[] { 1, 2, 3, 1, 2, 3, 10, 20, 30 });
});
IEnumerator Immediate(List<int> l)
{
l.Add(1);
l.Add(2);
l.Add(3);
yield break;
}
IEnumerator DelayOne(List<int> l)
{
l.Add(10);
yield return null;
l.Add(20);
l.Add(30);
}
[UnityTest] [UnityTest]
public IEnumerator WaitForSecondsTest() => UniTask.ToCoroutine(async () => public IEnumerator WaitForSecondsTest() => UniTask.ToCoroutine(async () =>
{ {