diff --git a/src/UniTask.NetCoreSandbox/Program.cs b/src/UniTask.NetCoreSandbox/Program.cs index e383db7..78dca8b 100644 --- a/src/UniTask.NetCoreSandbox/Program.cs +++ b/src/UniTask.NetCoreSandbox/Program.cs @@ -86,34 +86,16 @@ namespace NetCoreSandbox await Task.Delay(10, cancellationToken); } - private async UniTaskVoid HogeAsync() + + + static void Main(string[] args) { - } - static async Task Main(string[] args) - { - await foreach (var item in UniTaskAsyncEnumerable.Range(1, 10) - .SelectAwait(x => UniTask.Run(() => x)) - .TakeLast(6) - - - - ) - { - - - - Console.WriteLine(item); - } - -// AsyncEnumerable.Range(1,10).FirstAsync( - // AsyncEnumerable.Range(1, 10).GroupBy(x=>x).Select(x=>x.first + var channel = Channel.CreateSingleConsumerUnbounded(); - // AsyncEnumerable.Range(1,10).WithCancellation(CancellationToken.None).WithCancellation - //Enumerable.Range(1,10).ToHashSet( } diff --git a/src/UniTask.NetCoreTests/AsyncReactivePropertyTest.cs b/src/UniTask.NetCoreTests/AsyncReactivePropertyTest.cs new file mode 100644 index 0000000..3350763 --- /dev/null +++ b/src/UniTask.NetCoreTests/AsyncReactivePropertyTest.cs @@ -0,0 +1,57 @@ +using Cysharp.Threading.Tasks; +using FluentAssertions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Channels; +using Cysharp.Threading.Tasks.Linq; +using System.Threading.Tasks; +using Xunit; + +namespace NetCoreTests +{ + public class AsyncReactivePropertyTest + { + [Fact] + public async Task Iteration() + { + var rp = new AsyncReactiveProperty(99); + + var f = await rp.FirstAsync(); + f.Should().Be(99); + + var array = rp.Take(5).ToArrayAsync(); + + rp.Value = 100; + rp.Value = 100; + rp.Value = 100; + rp.Value = 131; + + var ar = await array; + + ar.Should().BeEquivalentTo(new[] { 99, 100, 100, 100, 131 }); + } + + [Fact] + public async Task WithoutCurrent() + { + var rp = new AsyncReactiveProperty(99); + + var array = rp.WithoutCurrent().Take(5).ToArrayAsync(); + + rp.Value = 100; + rp.Value = 100; + rp.Value = 100; + rp.Value = 131; + rp.Value = 191; + + var ar = await array; + + ar.Should().BeEquivalentTo(new[] { 100, 100, 100, 131, 191 }); + } + } + + +} diff --git a/src/UniTask/Assets/Plugins/UniTask/Runtime/AsyncReactiveProperty.cs b/src/UniTask/Assets/Plugins/UniTask/Runtime/AsyncReactiveProperty.cs index 21963e5..1866ce6 100644 --- a/src/UniTask/Assets/Plugins/UniTask/Runtime/AsyncReactiveProperty.cs +++ b/src/UniTask/Assets/Plugins/UniTask/Runtime/AsyncReactiveProperty.cs @@ -43,9 +43,14 @@ namespace Cysharp.Threading.Tasks this.triggerEvent = default; } + public IUniTaskAsyncEnumerable WithoutCurrent() + { + return new WithoutCurrentEnumerable(this); + } + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken) { - return new Enumerator(this, cancellationToken); + return new Enumerator(this, cancellationToken, true); } public void Dispose() @@ -53,6 +58,21 @@ namespace Cysharp.Threading.Tasks triggerEvent.SetCanceled(CancellationToken.None); } + class WithoutCurrentEnumerable : IUniTaskAsyncEnumerable + { + readonly AsyncReactiveProperty parent; + + public WithoutCurrentEnumerable(AsyncReactiveProperty parent) + { + this.parent = parent; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(parent, cancellationToken, false); + } + } + sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator, IResolveCancelPromise { static Action cancellationCallback = CancellationCallback; @@ -62,11 +82,13 @@ namespace Cysharp.Threading.Tasks readonly CancellationTokenRegistration cancellationTokenRegistration; T value; bool isDisposed; + bool firstCall; - public Enumerator(AsyncReactiveProperty parent, CancellationToken cancellationToken) + public Enumerator(AsyncReactiveProperty parent, CancellationToken cancellationToken, bool publishCurrentValue) { this.parent = parent; this.cancellationToken = cancellationToken; + this.firstCall = publishCurrentValue; parent.triggerEvent.Add(this); TaskTracker.TrackActiveTask(this, 3); @@ -81,6 +103,14 @@ namespace Cysharp.Threading.Tasks public UniTask MoveNextAsync() { + // raise latest value on first call. + if (firstCall) + { + firstCall = false; + value = parent.Value; + return CompletedTasks.True; + } + completionSource.Reset(); return new UniTask(this, completionSource.Version); }