mirror of
https://github.com/Cysharp/UniTask.git
synced 2026-05-16 20:20:45 +00:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
edf32496e4 | ||
|
|
785f5837d1 | ||
|
|
8c9272bc9f | ||
|
|
3e00735b3d | ||
|
|
00a1be8666 | ||
|
|
a2783d3c8a | ||
|
|
85d1a8a4a4 | ||
|
|
bbfb8354bb | ||
|
|
2f68e47443 | ||
|
|
89339ffb29 | ||
|
|
0535862fe6 | ||
|
|
a9e5fd4589 | ||
|
|
a3f3a28ea1 | ||
|
|
59020df965 | ||
|
|
ac01be79bf | ||
|
|
de5951f208 |
@@ -2,7 +2,7 @@ UniTask
|
|||||||
===
|
===
|
||||||
[](https://github.com/Cysharp/UniTask/actions) [](https://github.com/Cysharp/UniTask/releases)
|
[](https://github.com/Cysharp/UniTask/actions) [](https://github.com/Cysharp/UniTask/releases)
|
||||||
|
|
||||||
Provides an efficient async/await integration to Unity.
|
Provides an efficient allocation free async/await integration to Unity.
|
||||||
|
|
||||||
* Struct based `UniTask<T>` and custom AsyncMethodBuilder to achive zero allocation
|
* Struct based `UniTask<T>` and custom AsyncMethodBuilder to achive zero allocation
|
||||||
* All Unity AsyncOperations and Coroutine to awaitable
|
* All Unity AsyncOperations and Coroutine to awaitable
|
||||||
@@ -13,6 +13,9 @@ Provides an efficient async/await integration to Unity.
|
|||||||
* TaskTracker window to prevent memory leak
|
* TaskTracker window to prevent memory leak
|
||||||
* Highly compatible behaviour with Task/ValueTask/IValueTaskSource
|
* Highly compatible behaviour with Task/ValueTask/IValueTaskSource
|
||||||
|
|
||||||
|
Techinical details, see blog post: [UniTask v2 — Zero Allocation async/await for Unity, with Asynchronous LINQ
|
||||||
|
](https://medium.com/@neuecc/unitask-v2-zero-allocation-async-await-for-unity-with-asynchronous-linq-1aa9c96aa7dd)
|
||||||
|
|
||||||
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
||||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
@@ -778,7 +781,7 @@ After Unity 2019.3.4f1, Unity 2020.1a21, that support path query parameter of gi
|
|||||||
|
|
||||||
or add `"com.cysharp.unitask": "https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask"` to `Packages/manifest.json`.
|
or add `"com.cysharp.unitask": "https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask"` to `Packages/manifest.json`.
|
||||||
|
|
||||||
If you want to set a target version, UniTask is using `*.*.*` release tag so you can specify a version like `#2.0.15`. For example `https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask#2.0.15`.
|
If you want to set a target version, UniTask is using `*.*.*` release tag so you can specify a version like `#2.0.18`. For example `https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask#2.0.18`.
|
||||||
|
|
||||||
### Install via OpenUPM
|
### Install via OpenUPM
|
||||||
|
|
||||||
|
|||||||
101
src/UniTask.NetCore/NetCore/AsyncEnumerableExtensions.cs
Normal file
101
src/UniTask.NetCore/NetCore/AsyncEnumerableExtensions.cs
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
#if !NETSTANDARD2_0
|
||||||
|
|
||||||
|
#pragma warning disable 0649
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Threading.Tasks.Sources;
|
||||||
|
|
||||||
|
namespace Cysharp.Threading.Tasks
|
||||||
|
{
|
||||||
|
public static class AsyncEnumerableExtensions
|
||||||
|
{
|
||||||
|
public static IUniTaskAsyncEnumerable<T> AsUniTaskAsyncEnumerable<T>(this IAsyncEnumerable<T> source)
|
||||||
|
{
|
||||||
|
return new AsyncEnumerableToUniTaskAsyncEnumerable<T>(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IAsyncEnumerable<T> AsAsyncEnumerable<T>(this IUniTaskAsyncEnumerable<T> source)
|
||||||
|
{
|
||||||
|
return new UniTaskAsyncEnumerableToAsyncEnumerable<T>(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class AsyncEnumerableToUniTaskAsyncEnumerable<T> : IUniTaskAsyncEnumerable<T>
|
||||||
|
{
|
||||||
|
readonly IAsyncEnumerable<T> source;
|
||||||
|
|
||||||
|
public AsyncEnumerableToUniTaskAsyncEnumerable(IAsyncEnumerable<T> source)
|
||||||
|
{
|
||||||
|
this.source = source;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
return new Enumerator(source.GetAsyncEnumerator(cancellationToken));
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class Enumerator : IUniTaskAsyncEnumerator<T>
|
||||||
|
{
|
||||||
|
readonly IAsyncEnumerator<T> enumerator;
|
||||||
|
|
||||||
|
public Enumerator(IAsyncEnumerator<T> enumerator)
|
||||||
|
{
|
||||||
|
this.enumerator = enumerator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T Current => enumerator.Current;
|
||||||
|
|
||||||
|
public async UniTask DisposeAsync()
|
||||||
|
{
|
||||||
|
await enumerator.DisposeAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async UniTask<bool> MoveNextAsync()
|
||||||
|
{
|
||||||
|
return await enumerator.MoveNextAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class UniTaskAsyncEnumerableToAsyncEnumerable<T> : IAsyncEnumerable<T>
|
||||||
|
{
|
||||||
|
readonly IUniTaskAsyncEnumerable<T> source;
|
||||||
|
|
||||||
|
public UniTaskAsyncEnumerableToAsyncEnumerable(IUniTaskAsyncEnumerable<T> source)
|
||||||
|
{
|
||||||
|
this.source = source;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
return new Enumerator(source.GetAsyncEnumerator(cancellationToken));
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class Enumerator : IAsyncEnumerator<T>
|
||||||
|
{
|
||||||
|
readonly IUniTaskAsyncEnumerator<T> enumerator;
|
||||||
|
|
||||||
|
public Enumerator(IUniTaskAsyncEnumerator<T> enumerator)
|
||||||
|
{
|
||||||
|
this.enumerator = enumerator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T Current => enumerator.Current;
|
||||||
|
|
||||||
|
public ValueTask DisposeAsync()
|
||||||
|
{
|
||||||
|
return enumerator.DisposeAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueTask<bool> MoveNextAsync()
|
||||||
|
{
|
||||||
|
return enumerator.MoveNextAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -26,15 +26,14 @@ namespace Cysharp.Threading.Tasks
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<T> AsUniTask<T>(this ValueTask<T> task, bool useCurrentSynchronizationContext = true)
|
public static async UniTask<T> AsUniTask<T>(this ValueTask<T> task)
|
||||||
{
|
{
|
||||||
// NOTE: get _obj and _token directly for low overhead conversion but not yet implemented.
|
return await task;
|
||||||
return task.AsTask().AsUniTask(useCurrentSynchronizationContext);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask AsUniTask(this ValueTask task, bool useCurrentSynchronizationContext = true)
|
public static async UniTask AsUniTask(this ValueTask task)
|
||||||
{
|
{
|
||||||
return task.AsTask().AsUniTask(useCurrentSynchronizationContext);
|
await task;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NETSTANDARD2_0
|
#if NETSTANDARD2_0
|
||||||
|
|||||||
313
src/UniTask/Assets/Plugins/UniTask/Runtime/Linq/Subscribe.cs
Normal file
313
src/UniTask/Assets/Plugins/UniTask/Runtime/Linq/Subscribe.cs
Normal file
@@ -0,0 +1,313 @@
|
|||||||
|
using Cysharp.Threading.Tasks.Internal;
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using Subscribes = Cysharp.Threading.Tasks.Linq.Subscribe;
|
||||||
|
|
||||||
|
namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
{
|
||||||
|
public static partial class UniTaskAsyncEnumerable
|
||||||
|
{
|
||||||
|
// OnNext
|
||||||
|
|
||||||
|
public static IDisposable Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Action<TSource> action)
|
||||||
|
{
|
||||||
|
Error.ThrowArgumentNullException(source, nameof(source));
|
||||||
|
Error.ThrowArgumentNullException(action, nameof(action));
|
||||||
|
|
||||||
|
var cts = new CancellationTokenDisposable();
|
||||||
|
Subscribes.SubscribeCore(source, action, Subscribes.NopError, Subscribes.NopCompleted, cts.Token).Forget();
|
||||||
|
return cts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IDisposable Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTaskVoid> action)
|
||||||
|
{
|
||||||
|
Error.ThrowArgumentNullException(source, nameof(source));
|
||||||
|
Error.ThrowArgumentNullException(action, nameof(action));
|
||||||
|
|
||||||
|
var cts = new CancellationTokenDisposable();
|
||||||
|
Subscribes.SubscribeCore(source, action, Subscribes.NopError, Subscribes.NopCompleted, cts.Token).Forget();
|
||||||
|
return cts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IDisposable Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTaskVoid> action)
|
||||||
|
{
|
||||||
|
Error.ThrowArgumentNullException(source, nameof(source));
|
||||||
|
Error.ThrowArgumentNullException(action, nameof(action));
|
||||||
|
|
||||||
|
var cts = new CancellationTokenDisposable();
|
||||||
|
Subscribes.SubscribeCore(source, action, Subscribes.NopError, Subscribes.NopCompleted, cts.Token).Forget();
|
||||||
|
return cts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Action<TSource> action, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
Error.ThrowArgumentNullException(source, nameof(source));
|
||||||
|
Error.ThrowArgumentNullException(action, nameof(action));
|
||||||
|
|
||||||
|
Subscribes.SubscribeCore(source, action, Subscribes.NopError, Subscribes.NopCompleted, cancellationToken).Forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTaskVoid> action, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
Error.ThrowArgumentNullException(source, nameof(source));
|
||||||
|
Error.ThrowArgumentNullException(action, nameof(action));
|
||||||
|
|
||||||
|
Subscribes.SubscribeCore(source, action, Subscribes.NopError, Subscribes.NopCompleted, cancellationToken).Forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTaskVoid> action, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
Error.ThrowArgumentNullException(source, nameof(source));
|
||||||
|
Error.ThrowArgumentNullException(action, nameof(action));
|
||||||
|
|
||||||
|
Subscribes.SubscribeCore(source, action, Subscribes.NopError, Subscribes.NopCompleted, cancellationToken).Forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
// OnNext, OnError
|
||||||
|
|
||||||
|
public static IDisposable Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError)
|
||||||
|
{
|
||||||
|
Error.ThrowArgumentNullException(source, nameof(source));
|
||||||
|
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
||||||
|
Error.ThrowArgumentNullException(onError, nameof(onError));
|
||||||
|
|
||||||
|
var cts = new CancellationTokenDisposable();
|
||||||
|
Subscribes.SubscribeCore(source, onNext, onError, Subscribes.NopCompleted, cts.Token).Forget();
|
||||||
|
return cts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IDisposable Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTaskVoid> onNext, Action<Exception> onError)
|
||||||
|
{
|
||||||
|
Error.ThrowArgumentNullException(source, nameof(source));
|
||||||
|
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
||||||
|
Error.ThrowArgumentNullException(onError, nameof(onError));
|
||||||
|
|
||||||
|
var cts = new CancellationTokenDisposable();
|
||||||
|
Subscribes.SubscribeCore(source, onNext, onError, Subscribes.NopCompleted, cts.Token).Forget();
|
||||||
|
return cts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
Error.ThrowArgumentNullException(source, nameof(source));
|
||||||
|
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
||||||
|
Error.ThrowArgumentNullException(onError, nameof(onError));
|
||||||
|
|
||||||
|
Subscribes.SubscribeCore(source, onNext, onError, Subscribes.NopCompleted, cancellationToken).Forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTaskVoid> onNext, Action<Exception> onError, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
Error.ThrowArgumentNullException(source, nameof(source));
|
||||||
|
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
||||||
|
Error.ThrowArgumentNullException(onError, nameof(onError));
|
||||||
|
|
||||||
|
Subscribes.SubscribeCore(source, onNext, onError, Subscribes.NopCompleted, cancellationToken).Forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
// OnNext, OnCompleted
|
||||||
|
|
||||||
|
public static IDisposable Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Action<TSource> onNext, Action onCompleted)
|
||||||
|
{
|
||||||
|
Error.ThrowArgumentNullException(source, nameof(source));
|
||||||
|
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
||||||
|
Error.ThrowArgumentNullException(onCompleted, nameof(onCompleted));
|
||||||
|
|
||||||
|
var cts = new CancellationTokenDisposable();
|
||||||
|
Subscribes.SubscribeCore(source, onNext, Subscribes.NopError, onCompleted, cts.Token).Forget();
|
||||||
|
return cts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IDisposable Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTaskVoid> onNext, Action onCompleted)
|
||||||
|
{
|
||||||
|
Error.ThrowArgumentNullException(source, nameof(source));
|
||||||
|
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
||||||
|
Error.ThrowArgumentNullException(onCompleted, nameof(onCompleted));
|
||||||
|
|
||||||
|
var cts = new CancellationTokenDisposable();
|
||||||
|
Subscribes.SubscribeCore(source, onNext, Subscribes.NopError, onCompleted, cts.Token).Forget();
|
||||||
|
return cts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Action<TSource> onNext, Action onCompleted, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
Error.ThrowArgumentNullException(source, nameof(source));
|
||||||
|
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
||||||
|
Error.ThrowArgumentNullException(onCompleted, nameof(onCompleted));
|
||||||
|
|
||||||
|
Subscribes.SubscribeCore(source, onNext, Subscribes.NopError, onCompleted, cancellationToken).Forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTaskVoid> onNext, Action onCompleted, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
Error.ThrowArgumentNullException(source, nameof(source));
|
||||||
|
Error.ThrowArgumentNullException(onNext, nameof(onNext));
|
||||||
|
Error.ThrowArgumentNullException(onCompleted, nameof(onCompleted));
|
||||||
|
|
||||||
|
Subscribes.SubscribeCore(source, onNext, Subscribes.NopError, onCompleted, cancellationToken).Forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
// IObserver
|
||||||
|
|
||||||
|
public static IDisposable Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, IObserver<TSource> observer)
|
||||||
|
{
|
||||||
|
Error.ThrowArgumentNullException(source, nameof(source));
|
||||||
|
Error.ThrowArgumentNullException(observer, nameof(observer));
|
||||||
|
|
||||||
|
var cts = new CancellationTokenDisposable();
|
||||||
|
Subscribes.SubscribeCore(source, observer, cts.Token).Forget();
|
||||||
|
return cts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Subscribe<TSource>(this IUniTaskAsyncEnumerable<TSource> source, IObserver<TSource> observer, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
Error.ThrowArgumentNullException(source, nameof(source));
|
||||||
|
Error.ThrowArgumentNullException(observer, nameof(observer));
|
||||||
|
|
||||||
|
Subscribes.SubscribeCore(source, observer, cancellationToken).Forget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed class CancellationTokenDisposable : IDisposable
|
||||||
|
{
|
||||||
|
readonly CancellationTokenSource cts = new CancellationTokenSource();
|
||||||
|
|
||||||
|
public CancellationToken Token => cts.Token;
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (!cts.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
cts.Cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static class Subscribe
|
||||||
|
{
|
||||||
|
public static readonly Action<Exception> NopError = _ => { };
|
||||||
|
public static readonly Action NopCompleted = () => { };
|
||||||
|
|
||||||
|
public static async UniTaskVoid SubscribeCore<TSource>(IUniTaskAsyncEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError, Action onCompleted, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var e = source.GetAsyncEnumerator(cancellationToken);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (await e.MoveNextAsync())
|
||||||
|
{
|
||||||
|
onNext(e.Current);
|
||||||
|
}
|
||||||
|
onCompleted();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (onError == NopError)
|
||||||
|
{
|
||||||
|
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ex is OperationCanceledException) return;
|
||||||
|
|
||||||
|
onError(ex);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (e != null)
|
||||||
|
{
|
||||||
|
await e.DisposeAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async UniTaskVoid SubscribeCore<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTaskVoid> onNext, Action<Exception> onError, Action onCompleted, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var e = source.GetAsyncEnumerator(cancellationToken);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (await e.MoveNextAsync())
|
||||||
|
{
|
||||||
|
onNext(e.Current).Forget();
|
||||||
|
}
|
||||||
|
onCompleted();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (onError == NopError)
|
||||||
|
{
|
||||||
|
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ex is OperationCanceledException) return;
|
||||||
|
|
||||||
|
onError(ex);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (e != null)
|
||||||
|
{
|
||||||
|
await e.DisposeAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async UniTaskVoid SubscribeCore<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTaskVoid> onNext, Action<Exception> onError, Action onCompleted, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var e = source.GetAsyncEnumerator(cancellationToken);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (await e.MoveNextAsync())
|
||||||
|
{
|
||||||
|
onNext(e.Current, cancellationToken).Forget();
|
||||||
|
}
|
||||||
|
onCompleted();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (onError == NopError)
|
||||||
|
{
|
||||||
|
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ex is OperationCanceledException) return;
|
||||||
|
|
||||||
|
onError(ex);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (e != null)
|
||||||
|
{
|
||||||
|
await e.DisposeAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async UniTaskVoid SubscribeCore<TSource>(IUniTaskAsyncEnumerable<TSource> source, IObserver<TSource> observer, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var e = source.GetAsyncEnumerator(cancellationToken);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (await e.MoveNextAsync())
|
||||||
|
{
|
||||||
|
observer.OnNext(e.Current);
|
||||||
|
}
|
||||||
|
observer.OnCompleted();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (ex is OperationCanceledException) return;
|
||||||
|
|
||||||
|
observer.OnError(ex);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (e != null)
|
||||||
|
{
|
||||||
|
await e.DisposeAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 263479eb04c189741931fc0e2f615c2d
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -248,15 +248,18 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (queuedResult.Count != 0)
|
lock (queuedResult)
|
||||||
{
|
{
|
||||||
current = queuedResult.Dequeue();
|
if (queuedResult.Count != 0)
|
||||||
useCachedCurrent = true;
|
{
|
||||||
return current;
|
current = queuedResult.Dequeue();
|
||||||
}
|
useCachedCurrent = true;
|
||||||
else
|
return current;
|
||||||
{
|
}
|
||||||
return default; // undefined.
|
else
|
||||||
|
{
|
||||||
|
return default; // undefined.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
public _EveryUpdate(PlayerLoopTiming updateTiming, CancellationToken cancellationToken)
|
public _EveryUpdate(PlayerLoopTiming updateTiming, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
this.updateTiming = updateTiming;
|
this.updateTiming = updateTiming;
|
||||||
|
this.cancellationToken = cancellationToken;
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(this, 2);
|
TaskTracker.TrackActiveTask(this, 2);
|
||||||
PlayerLoopHelper.AddAction(updateTiming, this);
|
PlayerLoopHelper.AddAction(updateTiming, this);
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
this.dueTimePhase = true;
|
this.dueTimePhase = true;
|
||||||
this.updateTiming = updateTiming;
|
this.updateTiming = updateTiming;
|
||||||
this.ignoreTimeScale = ignoreTimeScale;
|
this.ignoreTimeScale = ignoreTimeScale;
|
||||||
|
this.cancellationToken = cancellationToken;
|
||||||
TaskTracker.TrackActiveTask(this, 2);
|
TaskTracker.TrackActiveTask(this, 2);
|
||||||
PlayerLoopHelper.AddAction(updateTiming, this);
|
PlayerLoopHelper.AddAction(updateTiming, this);
|
||||||
}
|
}
|
||||||
@@ -223,6 +224,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||||||
this.dueTimePhase = true;
|
this.dueTimePhase = true;
|
||||||
this.dueTimeFrameCount = dueTimeFrameCount;
|
this.dueTimeFrameCount = dueTimeFrameCount;
|
||||||
this.periodFrameCount = periodFrameCount;
|
this.periodFrameCount = periodFrameCount;
|
||||||
|
this.cancellationToken = cancellationToken;
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(this, 2);
|
TaskTracker.TrackActiveTask(this, 2);
|
||||||
PlayerLoopHelper.AddAction(updateTiming, this);
|
PlayerLoopHelper.AddAction(updateTiming, this);
|
||||||
|
|||||||
@@ -1285,12 +1285,20 @@ namespace Cysharp.Threading.Tasks
|
|||||||
continuationAction = null;
|
continuationAction = null;
|
||||||
var result = asyncOperation.webRequest;
|
var result = asyncOperation.webRequest;
|
||||||
asyncOperation = null;
|
asyncOperation = null;
|
||||||
|
if (result.isHttpError || result.isNetworkError)
|
||||||
|
{
|
||||||
|
throw new UnityWebRequestException(result);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var result = asyncOperation.webRequest;
|
var result = asyncOperation.webRequest;
|
||||||
asyncOperation = null;
|
asyncOperation = null;
|
||||||
|
if (result.isHttpError || result.isNetworkError)
|
||||||
|
{
|
||||||
|
throw new UnityWebRequestException(result);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1367,7 +1375,15 @@ namespace Cysharp.Threading.Tasks
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
completed = true;
|
completed = true;
|
||||||
core.TrySetResult(asyncOperation.webRequest);
|
var result = asyncOperation.webRequest;
|
||||||
|
if (result.isHttpError || result.isNetworkError)
|
||||||
|
{
|
||||||
|
core.TrySetException(new UnityWebRequestException(result));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core.TrySetResult(result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1526,7 +1542,14 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
if (asyncOperation.isDone)
|
if (asyncOperation.isDone)
|
||||||
{
|
{
|
||||||
core.TrySetResult(asyncOperation.webRequest);
|
if (asyncOperation.webRequest.isHttpError || asyncOperation.webRequest.isNetworkError)
|
||||||
|
{
|
||||||
|
core.TrySetException(new UnityWebRequestException(asyncOperation.webRequest));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core.TrySetResult(asyncOperation.webRequest);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -81,6 +81,12 @@ namespace Cysharp.Threading.Tasks
|
|||||||
<# if (!IsVoid(t)) { #>
|
<# if (!IsVoid(t)) { #>
|
||||||
var result = <#= $"asyncOperation.{t.returnField}" #>;
|
var result = <#= $"asyncOperation.{t.returnField}" #>;
|
||||||
asyncOperation = null;
|
asyncOperation = null;
|
||||||
|
<# if(t.returnType == "UnityWebRequest") { #>
|
||||||
|
if (result.isHttpError || result.isNetworkError)
|
||||||
|
{
|
||||||
|
throw new UnityWebRequestException(result);
|
||||||
|
}
|
||||||
|
<# } #>
|
||||||
return result;
|
return result;
|
||||||
<# } else { #>
|
<# } else { #>
|
||||||
asyncOperation = null;
|
asyncOperation = null;
|
||||||
@@ -91,6 +97,12 @@ namespace Cysharp.Threading.Tasks
|
|||||||
<# if (!IsVoid(t)) { #>
|
<# if (!IsVoid(t)) { #>
|
||||||
var result = <#= $"asyncOperation.{t.returnField}" #>;
|
var result = <#= $"asyncOperation.{t.returnField}" #>;
|
||||||
asyncOperation = null;
|
asyncOperation = null;
|
||||||
|
<# if(t.returnType == "UnityWebRequest") { #>
|
||||||
|
if (result.isHttpError || result.isNetworkError)
|
||||||
|
{
|
||||||
|
throw new UnityWebRequestException(result);
|
||||||
|
}
|
||||||
|
<# } #>
|
||||||
return result;
|
return result;
|
||||||
<# } else { #>
|
<# } else { #>
|
||||||
asyncOperation = null;
|
asyncOperation = null;
|
||||||
@@ -170,7 +182,19 @@ namespace Cysharp.Threading.Tasks
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
completed = true;
|
completed = true;
|
||||||
|
<# if(t.returnType == "UnityWebRequest") { #>
|
||||||
|
var result = asyncOperation.webRequest;
|
||||||
|
if (result.isHttpError || result.isNetworkError)
|
||||||
|
{
|
||||||
|
core.TrySetException(new UnityWebRequestException(result));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core.TrySetResult(result);
|
||||||
|
}
|
||||||
|
<# } else { #>
|
||||||
core.TrySetResult(<#= IsVoid(t) ? "AsyncUnit.Default" : $"asyncOperation.{t.returnField}" #>);
|
core.TrySetResult(<#= IsVoid(t) ? "AsyncUnit.Default" : $"asyncOperation.{t.returnField}" #>);
|
||||||
|
<# } #>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -345,7 +369,18 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
if (asyncOperation.isDone)
|
if (asyncOperation.isDone)
|
||||||
{
|
{
|
||||||
|
<# if(t.returnType == "UnityWebRequest") { #>
|
||||||
|
if (asyncOperation.webRequest.isHttpError || asyncOperation.webRequest.isNetworkError)
|
||||||
|
{
|
||||||
|
core.TrySetException(new UnityWebRequestException(asyncOperation.webRequest));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core.TrySetResult(asyncOperation.webRequest);
|
||||||
|
}
|
||||||
|
<# } else { #>
|
||||||
core.TrySetResult(<#= IsVoid(t) ? "AsyncUnit.Default" : $"asyncOperation.{t.returnField}" #>);
|
core.TrySetResult(<#= IsVoid(t) ? "AsyncUnit.Default" : $"asyncOperation.{t.returnField}" #>);
|
||||||
|
<# } #>
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
#if ENABLE_UNITYWEBREQUEST
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using UnityEngine.Networking;
|
||||||
|
|
||||||
|
namespace Cysharp.Threading.Tasks
|
||||||
|
{
|
||||||
|
public class UnityWebRequestException : Exception
|
||||||
|
{
|
||||||
|
public UnityWebRequest UnityWebRequest { get; }
|
||||||
|
public bool IsNetworkError { get; }
|
||||||
|
public bool IsHttpError { get; }
|
||||||
|
|
||||||
|
public UnityWebRequestException(UnityWebRequest unityWebRequest)
|
||||||
|
: base(unityWebRequest.error + Environment.NewLine + unityWebRequest.downloadHandler.text)
|
||||||
|
{
|
||||||
|
this.UnityWebRequest = unityWebRequest;
|
||||||
|
this.IsNetworkError = unityWebRequest.isNetworkError;
|
||||||
|
this.IsHttpError = unityWebRequest.isHttpError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 013a499e522703a42962a779b4d9850c
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "com.cysharp.unitask",
|
"name": "com.cysharp.unitask",
|
||||||
"displayName": "UniTask",
|
"displayName": "UniTask",
|
||||||
"version": "2.0.16",
|
"version": "2.0.18",
|
||||||
"unity": "2018.4",
|
"unity": "2018.4",
|
||||||
"description": "Provides an efficient async/await integration to Unity.",
|
"description": "Provides an efficient async/await integration to Unity.",
|
||||||
"keywords": [ "async/await", "async", "Task", "UniTask" ],
|
"keywords": [ "async/await", "async", "Task", "UniTask" ],
|
||||||
|
|||||||
@@ -415,15 +415,12 @@ public class SandboxMain : MonoBehaviour
|
|||||||
|
|
||||||
private async UniTaskVoid ExecuteAsync()
|
private async UniTaskVoid ExecuteAsync()
|
||||||
{
|
{
|
||||||
Debug.Log("1");
|
var req = UnityWebRequest.Get("https://google.com/");
|
||||||
{
|
|
||||||
var xs = await UniTaskAsyncEnumerable.TimerFrame(1).ToArrayAsync();
|
var v = await req.SendWebRequest().ToUniTask();
|
||||||
}
|
// req.Dispose();
|
||||||
Debug.Log("------------------");
|
Debug.Log($"{v.isDone} {v.isHttpError} {v.isNetworkError}");
|
||||||
{
|
Debug.Log(v.downloadHandler.text);
|
||||||
var xs = await UniTaskAsyncEnumerable.TimerFrame(1).ToArrayAsync();
|
|
||||||
Debug.Log("2");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user