Пример #1
0
        // 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;
                }
            }
        }
Пример #2
0
 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;
     }
 }
Пример #3
0
 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;
         }
     }
 }
Пример #4
0
 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)
     );
Пример #5
0
 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)
     );
Пример #6
0
        // 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);
            }
        }