mirror of https://github.com/Cysharp/UniTask
Compare commits
5 Commits
9da23aaf74
...
6a9a79cb97
Author | SHA1 | Date |
---|---|---|
|
6a9a79cb97 | |
|
4c3d6938ed | |
|
b4486802f2 | |
|
019f8aaf30 | |
|
663fa737f3 |
|
@ -159,6 +159,30 @@ namespace NetCoreTests.Linq
|
|||
list.Should().Equal(100, 200, 300, 400);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AwaitForeachBreak()
|
||||
{
|
||||
var finallyCalled = false;
|
||||
var enumerable = UniTaskAsyncEnumerable.Create<int>(async (writer, _) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await writer.YieldAsync(1);
|
||||
}
|
||||
finally
|
||||
{
|
||||
finallyCalled = true;
|
||||
}
|
||||
});
|
||||
|
||||
await foreach (var x in enumerable)
|
||||
{
|
||||
x.Should().Be(1);
|
||||
break;
|
||||
}
|
||||
finallyCalled.Should().BeTrue();
|
||||
}
|
||||
|
||||
async IAsyncEnumerable<int> Range(int from, int count)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
|
|
|
@ -52,6 +52,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||
public UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
writer.Dispose();
|
||||
return default;
|
||||
}
|
||||
|
||||
|
@ -127,7 +128,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||
}
|
||||
}
|
||||
|
||||
sealed class AsyncWriter : IUniTaskSource, IAsyncWriter<T>
|
||||
sealed class AsyncWriter : IUniTaskSource, IAsyncWriter<T>, IDisposable
|
||||
{
|
||||
readonly _Create enumerator;
|
||||
|
||||
|
@ -138,6 +139,15 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||
this.enumerator = enumerator;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
var status = core.GetStatus(core.Version);
|
||||
if (status == UniTaskStatus.Pending)
|
||||
{
|
||||
core.TrySetCanceled();
|
||||
}
|
||||
}
|
||||
|
||||
public void GetResult(short token)
|
||||
{
|
||||
core.GetResult(token);
|
||||
|
|
|
@ -20,8 +20,6 @@ namespace Cysharp.Threading.Tasks
|
|||
{
|
||||
ITriggerHandler<T> head; // head.prev is last
|
||||
ITriggerHandler<T> iteratingHead;
|
||||
|
||||
bool preserveRemoveSelf;
|
||||
ITriggerHandler<T> iteratingNode;
|
||||
|
||||
void LogError(Exception ex)
|
||||
|
@ -44,6 +42,7 @@ namespace Cysharp.Threading.Tasks
|
|||
while (h != null)
|
||||
{
|
||||
iteratingNode = h;
|
||||
var next = h.Next;
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -55,19 +54,8 @@ namespace Cysharp.Threading.Tasks
|
|||
Remove(h);
|
||||
}
|
||||
|
||||
if (preserveRemoveSelf)
|
||||
{
|
||||
preserveRemoveSelf = false;
|
||||
iteratingNode = null;
|
||||
var next = h.Next;
|
||||
Remove(h);
|
||||
h = next;
|
||||
}
|
||||
else
|
||||
{
|
||||
h = h.Next;
|
||||
}
|
||||
}
|
||||
|
||||
iteratingNode = null;
|
||||
if (iteratingHead != null)
|
||||
|
@ -97,7 +85,6 @@ namespace Cysharp.Threading.Tasks
|
|||
LogError(ex);
|
||||
}
|
||||
|
||||
preserveRemoveSelf = false;
|
||||
iteratingNode = null;
|
||||
var next = h.Next;
|
||||
Remove(h);
|
||||
|
@ -132,7 +119,6 @@ namespace Cysharp.Threading.Tasks
|
|||
LogError(ex);
|
||||
}
|
||||
|
||||
preserveRemoveSelf = false;
|
||||
iteratingNode = null;
|
||||
var next = h.Next;
|
||||
Remove(h);
|
||||
|
@ -167,7 +153,6 @@ namespace Cysharp.Threading.Tasks
|
|||
LogError(ex);
|
||||
}
|
||||
|
||||
preserveRemoveSelf = false;
|
||||
iteratingNode = null;
|
||||
var next = h.Next;
|
||||
Remove(h);
|
||||
|
@ -241,13 +226,6 @@ namespace Cysharp.Threading.Tasks
|
|||
{
|
||||
if (handler == null) throw new ArgumentNullException(nameof(handler));
|
||||
|
||||
if (iteratingNode != null && iteratingNode == handler)
|
||||
{
|
||||
// if remove self, reserve remove self after invoke completed.
|
||||
preserveRemoveSelf = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var prev = handler.Prev;
|
||||
var next = handler.Next;
|
||||
|
||||
|
@ -308,4 +286,3 @@ namespace Cysharp.Threading.Tasks
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
using Cysharp.Threading.Tasks;
|
||||
using FluentAssertions;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Threading;
|
||||
using UnityEngine.TestTools;
|
||||
|
||||
namespace Cysharp.Threading.TasksTests
|
||||
{
|
||||
public class AsyncReactivePropertyTest
|
||||
{
|
||||
private int _callCounter;
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator WaitCancelWait() => UniTask.ToCoroutine(async () =>
|
||||
{
|
||||
// Test case for https://github.com/Cysharp/UniTask/issues/444
|
||||
|
||||
var property = new AsyncReactiveProperty<int>(0);
|
||||
|
||||
var cts1 = new CancellationTokenSource();
|
||||
var cts2 = new CancellationTokenSource();
|
||||
WaitForProperty(property, cts1.Token);
|
||||
WaitForProperty(property, cts2.Token);
|
||||
|
||||
_callCounter = 0;
|
||||
property.Value = 1;
|
||||
_callCounter.Should().Be(2);
|
||||
|
||||
cts2.Cancel();
|
||||
cts2.Dispose();
|
||||
cts1.Cancel();
|
||||
cts1.Dispose();
|
||||
|
||||
var cts3 = new CancellationTokenSource();
|
||||
WaitForProperty(property, cts3.Token);
|
||||
|
||||
_callCounter = 0;
|
||||
property.Value = 2;
|
||||
_callCounter.Should().Be(1);
|
||||
|
||||
cts3.Cancel();
|
||||
cts3.Dispose();
|
||||
await UniTask.CompletedTask;
|
||||
});
|
||||
|
||||
private async void WaitForProperty(AsyncReactiveProperty<int> property, CancellationToken token)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
await property.WaitAsync(token);
|
||||
_callCounter++;
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 27665955eefb4448969b8cc4dd204600
|
||||
timeCreated: 1676129650
|
Loading…
Reference in New Issue