public async void Error_2_Consumers() { var push = new MulticastAsyncEnumerable <int>(); var en1 = push.GetAsyncEnumerator(); var en2 = push.GetAsyncEnumerator(); var task1 = Task.Run(async() => { await en1.AssertFailure(typeof(InvalidOperationException), 1, 2, 3, 4, 5); }); var task2 = Task.Run(async() => { await en2.AssertFailure(typeof(InvalidOperationException), 1, 2, 3, 4, 5); }); for (var i = 1; i <= 5; i++) { await push.Next(i); } await push.Error(new InvalidOperationException()); await task1; await task2; }
public new async Task StopAsync() { // Wait, until all messages are published, at least if we're connected while (IsConnected && PendingApplicationMessagesCount > 0) { await Task.Delay(20); } // In my tests, the dispose method was not called on StopAsync => let's complete the received message here try { await _receivedMessages.Complete(); } catch (Exception e) { await _receivedMessages.Error(e); } }
public async void Error_No_Consumers() { var push = new MulticastAsyncEnumerable <int>(); for (var i = 1; i <= 5; i++) { await push.Next(i); } await push.Error(new InvalidOperationException()); await push.AssertFailure(typeof(InvalidOperationException)); }
public IAsyncEnumerable <TResult> ExecuteParallelAsync(IAsyncEnumerable <AsyncStreamQueueItem <TResult, TSource> > inputItems, int maxConcurrentTasks, CancellationToken cancellationToken) { var throttler = new SemaphoreSlim(maxConcurrentTasks); var nextLock = new SemaphoreSlim(1, 1); var multicastStream = new MulticastAsyncEnumerable <TResult>(); HashSet <Task> runningStreams = new HashSet <Task>(); HandleInputStreams(); return(multicastStream); async void HandleInputStreams() { try { await foreach (AsyncStreamQueueItem <TResult, TSource> inputItem in inputItems.WithCancellation(cancellationToken)) { var stream = ExecuteItem(throttler, inputItem, cancellationToken); lock (runningStreams) { runningStreams.Add(ConsumeSubStream(stream)); } } await Task.WhenAll(runningStreams); await nextLock.WaitAsync(cancellationToken); try { await multicastStream.Complete(); } finally { nextLock.Release(); } } catch (Exception e) { await multicastStream.Error(e); } } async Task ConsumeSubStream(IAsyncEnumerable <TResult> source) { try { await foreach (var item in source.WithCancellation(cancellationToken)) { await nextLock.WaitAsync(cancellationToken); try { await multicastStream.Next(item); } finally { nextLock.Release(); } } } catch (Exception e) { await multicastStream.Error(e); } } }