public static IAsyncEnumerable <TSource> ToAsyncEnumerable <TSource>(this IObservable <TSource> source)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            return(Create(() =>
            {
                var observer = new ToAsyncEnumerableObserver <TSource>();
                observer.Queue = new Queue <Either <TSource, Exception, bool> >();

                var subscription = source.Subscribe(observer);

                return Create(
                    (ct, tcs) =>
                {
                    lock (observer.Queue)
                    {
                        if (observer.Queue.Count > 0)
                        {
                            var n = observer.Queue.Dequeue();
                            n.Switch(
                                x =>
                            {
                                observer.Current = x;
                                tcs.TrySetResult(true);
                            },
                                ex =>
                            {
                                tcs.TrySetException(ex);
                            },
                                _ =>
                            {
                                tcs.TrySetResult(false);
                            }
                                );
                        }
                        else
                        {
                            observer.TaskCompletionSource = tcs;
                        }
                    }

                    return tcs.Task;
                },
                    () => observer.Current,
                    () =>
                {
                    subscription.Dispose();
                    // Should we cancel in-flight operations somehow?
                });
            }));
        }
Beispiel #2
0
        public static IAsyncEnumerable <TSource> ToAsyncEnumerable <TSource>(this IObservable <TSource> source)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            return(CreateEnumerable(
                       () =>
            {
                var observer = new ToAsyncEnumerableObserver <TSource>();

                var subscription = source.Subscribe(observer);

                return CreateEnumerator(
                    (ct, tcs) =>
                {
                    var hasValue = false;
                    var hasCompleted = false;
                    var error = default(Exception);

                    lock (observer.SyncRoot)
                    {
                        if (observer.Values.Count > 0)
                        {
                            hasValue = true;
                            observer.Current = observer.Values.Dequeue();
                        }
                        else if (observer.HasCompleted)
                        {
                            hasCompleted = true;
                        }
                        else if (observer.Error != null)
                        {
                            error = observer.Error;
                        }
                        else
                        {
                            observer.TaskCompletionSource = tcs;
                        }
                    }

                    if (hasValue)
                    {
                        tcs.TrySetResult(true);
                    }
                    else if (hasCompleted)
                    {
                        tcs.TrySetResult(false);
                    }
                    else if (error != null)
                    {
                        tcs.TrySetException(error);
                    }

                    return tcs.Task;
                },
                    () => observer.Current,
                    () =>
                {
                    subscription.Dispose();
                    // Should we cancel in-flight operations somehow?
                });
            }));
        }