示例#1
0
        /// <summary>
        /// Receive multiple messages from a pipe
        /// </summary>
        public static async IAsyncEnumerable <T> ReceiveAsync <T>(PipeReader source, MessagePipeOptions options = default)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            options = options.Normalize();

            while (true)
            {
                // obtain the next buffer
                options.OnLog("ReceiveAsync obtaining buffer...");
                if (!source.TryRead(out var result))
                {
                    result = await source.ReadAsync(options.CancellationToken).ConfigureAwait(false);
                }
                if (result.IsCanceled)
                {
                    ThrowCancelled();
                }

                // consume the buffer
                var buffer = result.Buffer;
                options.OnLog($"ReceiveAsync got {buffer.Length} bytes");
                int processed = 0;
                while (options.TryRead <T>(ref buffer, out var item))
                {
                    processed++;
                    yield return(item);
                }

                if (processed == 0 && result.IsCompleted) // check for termination
                {
                    // we have everything, and there will never be any more; was it clean?
                    if (!buffer.IsEmpty)
                    {
                        ThrowInputCompletedWithPartialPayload();
                    }
                    break;
                }

                // mark what we consumed (the "ref buffer" means we've sliced it already)
                source.AdvanceTo(buffer.Start, buffer.End);
            }
            if (options.MarkComplete)
            {
                await source.CompleteAsync().ConfigureAwait(false);
            }
            options.OnLog("ReceiveAsync completed successfully");
        }
示例#2
0
        /// <summary>
        /// Send multiple messages over a pipe
        /// </summary>
        public static async ValueTask SendAsync <T>(PipeWriter destination, IAsyncEnumerable <T> source, MessagePipeOptions options = default)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            options = options.Normalize();
            await foreach (var message in source.WithCancellation(options.CancellationToken).ConfigureAwait(false))
            {
                options.OnLog("SendAsync writing...");
                options.Write(destination, message);
                options.OnLog("SendAsync flushing...");
                CheckFlushResult(await destination.FlushAsync(options.CancellationToken).ConfigureAwait(false));
                options.OnLog("SendAsync flushed");
            }
            if (options.MarkComplete)
            {
                await destination.CompleteAsync().ConfigureAwait(false);
            }
        }
示例#3
0
        /// <summary>
        /// Send multiple messages over a stream
        /// </summary>
        public static async ValueTask SendAsync <T>(Stream destination, IAsyncEnumerable <T> source, MessagePipeOptions options = default)
        {
            var writer = StreamConnection.GetWriter(destination, options.PipeOptions);
            var tcs    = new TaskCompletionSource <object>();

#pragma warning disable CS0618                                // this *is* a Pipe; this is fine
            writer.OnReaderCompleted(s_ReaderCompleted, tcs); // attach to detect when the pipe is drained
#pragma warning restore CS0618

            await SendAsync <T>(writer, source, options.Without(MessagePipeFlags.LeaveOpen)).ConfigureAwait(false); // send the data

            await tcs.Task.ConfigureAwait(false);                                                                   // wait for the pipe to drain

            await destination.FlushAsync().ConfigureAwait(false);                                                   // flush the stream
        }
示例#4
0
 /// <summary>
 /// Receive multiple messages from a pipe
 /// </summary>
 public static ValueTask ReceiveAsync <T>(PipeReader source, ChannelWriter <T> destination, MessagePipeOptions options = default)
 => WriteToChannelAsync(ReceiveAsync <T>(source, options), destination, options.CancellationToken, options.MarkComplete);
示例#5
0
 /// <summary>
 /// Receive multiple messages from a stream
 /// </summary>
 public static IAsyncEnumerable <T> ReceiveAsync <T>(Stream source, MessagePipeOptions options = default)
 => ReceiveAsync <T>(StreamConnection.GetReader(source, options.PipeOptions), options);
示例#6
0
 /// <summary>
 /// Send multiple messages over a pipe
 /// </summary>
 public static ValueTask SendAsync <T>(PipeWriter destination, ChannelReader <T> source, MessagePipeOptions options = default)
 => SendAsync <T>(destination, AsAsyncEnumerable <T>(source, options.CancellationToken), options);