예제 #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);
            }
        }