// Transform public static async Task Transform <TIn, TOut>( this ChannelReader <TIn> reader, ChannelWriter <TOut> writer, Func <TIn, TOut> transformer, ChannelCompletionMode channelCompletionMode = ChannelCompletionMode.CompleteAndPropagateError, CancellationToken cancellationToken = default) { try { while (await reader.WaitToReadAsync(cancellationToken).ConfigureAwait(false)) { if (reader.TryRead(out var item)) { var newItem = transformer.Invoke(item); await writer.WriteAsync(newItem, cancellationToken).ConfigureAwait(false); } } if ((channelCompletionMode & ChannelCompletionMode.Complete) != 0) { writer.TryComplete(); } } catch (OperationCanceledException) { throw; } catch (Exception e) { if (channelCompletionMode == ChannelCompletionMode.CompleteAndPropagateError) { writer.TryComplete(e); } else { throw; } } }
public static async Task Copy <T>( this ChannelReader <T> reader, ChannelWriter <T> writer, ChannelCompletionMode channelCompletionMode, CancellationToken cancellationToken = default) { try { while (await reader.WaitToReadAsync(cancellationToken).ConfigureAwait(false)) { while (reader.TryRead(out var value)) { await writer.WriteAsync(value, cancellationToken).ConfigureAwait(false); } } if ((channelCompletionMode & ChannelCompletionMode.PropagateCompletion) != 0) { writer.TryComplete(); } } catch (OperationCanceledException oce) { if ((channelCompletionMode & ChannelCompletionMode.PropagateCancellation) != 0) { writer.TryComplete(oce); } throw; } catch (Exception e) { if ((channelCompletionMode & ChannelCompletionMode.PropagateError) != 0) { writer.TryComplete(e); } throw; } }
public static async Task CopyTo <T>(this IAsyncEnumerable <T> source, ChannelWriter <T> writer, ChannelCompletionMode channelCompletionMode, CancellationToken cancellationToken = default) { try { await foreach (var item in source.WithCancellation(cancellationToken).ConfigureAwait(false)) { await writer.WriteAsync(item, cancellationToken).ConfigureAwait(false); } if ((channelCompletionMode & ChannelCompletionMode.Complete) != 0) { writer.TryComplete(); } } catch (OperationCanceledException) { throw; } catch (Exception e) { if (channelCompletionMode == ChannelCompletionMode.CompleteAndPropagateError) { writer.TryComplete(e); } else { throw; } } }
public static Task Connect <T1, T2>( this Channel <T1> channel1, Channel <T2> channel2, Func <T1, T2> adapter12, Func <T2, T1> adapter21, ChannelCompletionMode channelCompletionMode, CancellationToken cancellationToken = default) => Task.WhenAll( Task.Run(() => channel1.Reader.Transform( channel2, adapter12, channelCompletionMode, cancellationToken), CancellationToken.None), Task.Run(() => channel2.Reader.Transform( channel1, adapter21, channelCompletionMode, cancellationToken), CancellationToken.None) );
public static Task Connect <T>( this Channel <T> channel1, Channel <T> channel2, ChannelCompletionMode channelCompletionMode, CancellationToken cancellationToken = default) => Task.WhenAll( Task.Run(() => channel1.Reader.Copy( channel2, channelCompletionMode, cancellationToken), CancellationToken.None), Task.Run(() => channel2.Reader.Copy( channel1, channelCompletionMode, cancellationToken), CancellationToken.None) );
// ConcurrentTransform public static async Task ConcurrentTransform <TIn, TOut>( this ChannelReader <TIn> reader, ChannelWriter <TOut> writer, Func <TIn, TOut> transformer, int concurrencyLevel = -1, ChannelCompletionMode channelCompletionMode = ChannelCompletionMode.CompleteAndPropagateError, CancellationToken cancellationToken = default) { if (concurrencyLevel < 0) { concurrencyLevel = HardwareInfo.GetProcessorCountFactor(); } var semaphore = new SemaphoreSlim(concurrencyLevel, concurrencyLevel); Exception?error = null; async Task Worker() { try { for (;;) { await semaphore !.WaitAsync(cancellationToken).ConfigureAwait(false); try { if (!await reader.WaitToReadAsync(cancellationToken).ConfigureAwait(false)) { break; } if (!reader.TryRead(out var item)) { continue; } var newItem = transformer.Invoke(item); await writer.WriteAsync(newItem, cancellationToken).ConfigureAwait(false); } finally { semaphore.Release(); } } } catch (OperationCanceledException) { throw; } catch (Exception e) { if (channelCompletionMode == ChannelCompletionMode.CompleteAndPropagateError) { error = e; } else { throw; } } } var workers = new Task[concurrencyLevel]; for (var i = 0; i < concurrencyLevel; i++) { workers[i] = Task.Run(Worker, cancellationToken); } await Task.WhenAll(workers).ConfigureAwait(false); if ((channelCompletionMode & ChannelCompletionMode.Complete) != 0) { writer.TryComplete(error); } }