Exemple #1
0
        /// <summary>
        /// Merges elements from all inner async-enumerable sequences concurrently into a single async-enumerable sequence.
        /// All thrown Exception are thrown at the end of the enumeration of all streams. Multiple Exceptions are thrown as AggregateException.
        /// </summary>
        /// <typeparam name="T">The type of the elements in the source sequences.</typeparam>
        /// <param name="sources">Observable sequence of inner async-enumerable sequences.</param>
        /// <param name="cancellationToken">Cancellation Token to cancel the enumeration</param>
        /// <returns>The async-enumerable sequence that merges the elements of the inner sequences.</returns>
        /// <exception cref="T:System.ArgumentNullException"><paramref name="sources" /> is null.</exception>
        public static IAsyncEnumerable <T> MergeConcurrently <T>(this IAsyncEnumerable <IAsyncEnumerable <T> > sources, CancellationToken cancellationToken = default)
        {
            var       queue           = new UnicastAsyncEnumerable <T>();
            var       tasks           = new List <Task>();
            Exception thrownException = null;

            StreamSources();

            return(queue);

            async void StreamSources()
            {
                try
                {
                    await foreach (var stream in sources.WithCancellation(cancellationToken))
                    {
                        tasks.Add(StreamSource(stream));
                    }

                    // After the last stream arrived, we have to wait until all of those streams have completely finished with streaming
                    await Task.WhenAll(tasks);

                    if (thrownException != null)
                    {
                        await queue.Error(thrownException);
                    }
                }
                catch (OperationCanceledException)
                {
                }
                catch (Exception e)
                {
                    ExceptionHelper.AddException(ref thrownException, e);
                    await queue.Error(thrownException);
                }
                finally
                {
                    await queue.Complete();
                }
            }

            async Task StreamSource(IAsyncEnumerable <T> source)
            {
                try
                {
                    await foreach (var item in source.WithCancellation(cancellationToken))
                    {
                        await queue.Next(item);
                    }
                }
                catch (OperationCanceledException)
                {
                }
                catch (Exception e)
                {
                    ExceptionHelper.AddException(ref thrownException, e);;
                }
            }
        }
Exemple #2
0
        /// <summary>
        /// Merges elements from all inner async-enumerable sequences concurrently into a single async-enumerable sequence.
        /// Enumeration stops on first thrown Exception of any inner streams.
        /// </summary>
        /// <typeparam name="T">The type of the elements in the source sequences.</typeparam>
        /// <param name="sources">Observable sequence of inner async-enumerable sequences.</param>
        /// <returns>The async-enumerable sequence that merges the elements of the inner sequences.</returns>
        /// <exception cref="T:System.ArgumentNullException"><paramref name="sources" /> is null.</exception>
        public static IAsyncEnumerable <T> MergeConcurrentlyUntilFirstException <T>(this IAsyncEnumerable <IAsyncEnumerable <T> > sources)
        {
            var queue = new UnicastAsyncEnumerable <T>();
            var tasks = new List <Task>();

            StreamSources();

            return(queue);

            async void StreamSources()
            {
                try
                {
                    await foreach (var stream in sources)
                    {
                        tasks.Add(StreamSource(stream));
                    }

                    // After the last stream arrived, we have to wait until all of those streams have completely finished with streaming
                    await Task.WhenAll(tasks);
                }
                catch (OperationCanceledException)
                {
                }
                catch (Exception e)
                {
                    await queue.Error(e);
                }
                finally
                {
                    await queue.Complete();
                }
            }

            async Task StreamSource(IAsyncEnumerable <T> source)
            {
                try
                {
                    await foreach (var item in source)
                    {
                        await queue.Next(item);
                    }
                }
                catch (OperationCanceledException)
                {
                }
                catch (Exception e)
                {
                    await queue.Error(e);
                }
            }
        }
Exemple #3
0
        public async void Call_After_Done_2()
        {
            var push = new UnicastAsyncEnumerable <int>();
            await push.Error(new InvalidOperationException());

            await push.Complete();

            await push.Next(1);

            await push.Error(new IndexOutOfRangeException());

            await push.AssertFailure(typeof(InvalidOperationException));
        }
        public static async IAsyncEnumerable <T> If <T>(this IAsyncEnumerable <T> source, Func <T, bool> ifSelector,
                                                        Func <IAsyncEnumerable <T>, IAsyncEnumerable <T> > ifFunction, Func <IAsyncEnumerable <T>, IAsyncEnumerable <T> > elseFunction = null, [EnumeratorCancellation] CancellationToken cancellationToken = default)
        {
            var ifSourceStream   = new UnicastAsyncEnumerable <T>();
            var elseSourceStream = new UnicastAsyncEnumerable <T>();
            var ifResultStream   = ifFunction(ifSourceStream);
            var elseResultStream = elseFunction?.Invoke(elseSourceStream) ?? elseSourceStream;

            HandleStream();

            var result = ifResultStream.MergeConcurrently(elseResultStream);

            try
            {
                await foreach (var item in result.WithCancellation(cancellationToken))
                {
                    yield return(item);
                }
            }
            finally
            {
                await ifSourceStream.Complete();

                await elseSourceStream.Complete();
            }


            async void HandleStream()
            {
                try
                {
                    await foreach (var item in source.WithCancellation(cancellationToken))
                    {
                        if (ifSelector(item))
                        {
                            await ifSourceStream.Next(item);
                        }
                        else
                        {
                            await elseSourceStream.Next(item);
                        }
                    }
                }
                catch (OperationCanceledException)
                {
                }
                catch (Exception e)
                {
                    await elseSourceStream.Error(e);
                }
                finally
                {
                    await ifSourceStream.Complete();

                    await elseSourceStream.Complete();
                }
            }
        }
Exemple #5
0
        public async void Offline_Error()
        {
            var push = new UnicastAsyncEnumerable <int>();

            for (var i = 1; i <= 5; i++)
            {
                await push.Next(i);
            }
            await push.Error(new InvalidOperationException());

            await push.AssertFailure(typeof(InvalidOperationException), 1, 2, 3, 4, 5);
        }
Exemple #6
0
        public async void Error_After_Dispose()
        {
            var push = new UnicastAsyncEnumerable <int>();

            var t = push.Take(1).AssertResult(1);

            await push.Next(1);

            await t;

            await push.Error(new InvalidOperationException());
        }
Exemple #7
0
        public async void Call_After_Done()
        {
            var push = new UnicastAsyncEnumerable <int>();
            await push.Complete();

            await push.Error(new InvalidOperationException());

            await push.Next(1);

            await push.Complete();

            await push.AssertResult();
        }