public static AsyncAsyncSubject <TSource> GetAwaiter <TSource>(this IConnectableAsyncObservable <TSource> source) { if (source == null) { throw new ArgumentNullException(nameof(source)); } var subject = new SequentialAsyncAsyncSubject <TSource>(); var subscribeTask = source.SubscribeSafeAsync(subject); subscribeTask.AsTask().ContinueWith(t => { if (t.Exception != null) { subject.OnErrorAsync(t.Exception); // NB: Should not occur due to use of SubscribeSafeAsync. } else { source.ConnectAsync(); } }); return(subject); }
public static AsyncAsyncSubject <TSource> RunAsync <TSource>(this IConnectableAsyncObservable <TSource> source, CancellationToken token) { if (source == null) { throw new ArgumentNullException(nameof(source)); } var subject = new SequentialAsyncAsyncSubject <TSource>(); if (token.IsCancellationRequested) { var ignored = subject.OnErrorAsync(new OperationCanceledException(token)); return(subject); } var d = new CompositeAsyncDisposable(); var subscribeTask = source.SubscribeSafeAsync(subject); subscribeTask.ContinueWith(t => { if (t.Exception != null) { subject.OnErrorAsync(t.Exception); // NB: Should not occur due to use of SubscribeSafeAsync. } else { var ignored = d.AddAsync(t.Result); source.ConnectAsync().ContinueWith(t2 => { if (t2.Exception == null) { var ignored2 = d.AddAsync(t2.Result); } }); } }); if (token.CanBeCanceled) { token.Register(() => { var ignored = d.DisposeAsync(); }); } return(subject); }
public static IAsyncObservable <TSource> RefCount <TSource>(this IConnectableAsyncObservable <TSource> source) { if (source == null) { throw new ArgumentNullException(nameof(source)); } var gate = new AsyncLock(); var count = 0; var connectable = default(IAsyncDisposable); return(Create <TSource>(async observer => { var subscription = await source.SubscribeSafeAsync(observer).ConfigureAwait(false); using (await gate.LockAsync().ConfigureAwait(false)) { if (++count == 1) { connectable = await source.ConnectAsync().ConfigureAwait(false); } } return AsyncDisposable.Create(async() => { await subscription.DisposeAsync().ConfigureAwait(false); using (await gate.LockAsync().ConfigureAwait(false)) { if (--count == 0) { await connectable.DisposeAsync().ConfigureAwait(false); } } }); })); }