public async Task SendLargePayloadOnManyChannels() { if (await this.ExecuteInIsolationAsync()) { byte[][] serverBuffers = Enumerable.Range(1, ChannelCount).Select(i => new byte[SegmentSize]).ToArray(); (MultiplexingStream mxServer, MultiplexingStream mxClient) = await Task.WhenAll( MultiplexingStream.CreateAsync(this.serverPipe, this.TimeoutToken).WithCancellation(this.TimeoutToken), MultiplexingStream.CreateAsync(this.clientPipe, this.TimeoutToken).WithCancellation(this.TimeoutToken)); await this.WaitForQuietPeriodAsync(); // Warm up await RunAsync(ChannelCount * 2); long memory1 = GC.GetTotalMemory(true); var sw = Stopwatch.StartNew(); await RunAsync(SegmentCount); sw.Stop(); long memory2 = GC.GetTotalMemory(false); long allocated = memory2 - memory1; this.Logger.WriteLine("{0} bytes allocated ({1} per segment)", allocated, allocated / SegmentCount); this.Logger.WriteLine("{0} bytes transmitted in each of {1} segments in {2}ms on {3} channel(s)", SegmentSize, SegmentCount, sw.ElapsedMilliseconds, ChannelCount); async Task RunAsync(int segmentCount) { Requires.Argument(segmentCount >= ChannelCount, nameof(segmentCount), "Cannot send {0} segments over {1} channels.", segmentCount, ChannelCount); await Task.WhenAll( Task.Run(async delegate { await Task.WhenAll( Enumerable.Range(1, ChannelCount).Select(c => Task.Run(async delegate { byte[] serverBuffer = serverBuffers[c - 1]; MultiplexingStream.Channel?channel = await mxServer.OfferChannelAsync(string.Empty, this.TimeoutToken).WithCancellation(this.TimeoutToken); for (int i = 0; i < segmentCount / ChannelCount; i++) { await channel.Output.WriteAsync(serverBuffer, this.TimeoutToken); } }))); }), Task.Run(async delegate { await Task.WhenAll( Enumerable.Range(1, ChannelCount).Select(c => Task.Run(async delegate { MultiplexingStream.Channel?channel = await mxClient.AcceptChannelAsync(string.Empty, this.TimeoutToken).WithCancellation(this.TimeoutToken); int expectedTotalBytesRead = segmentCount / ChannelCount * SegmentSize; int totalBytesRead = 0; do { System.IO.Pipelines.ReadResult readResult = await channel.Input.ReadAsync(this.TimeoutToken); totalBytesRead += (int)readResult.Buffer.Length; channel.Input.AdvanceTo(readResult.Buffer.End); readResult.ScrubAfterAdvanceTo(); }while (totalBytesRead < expectedTotalBytesRead); Assert.Equal(expectedTotalBytesRead, totalBytesRead); }))); })).WithCancellation(this.TimeoutToken); } } }
/// <summary> /// Attempt to synchronously read data the <see cref="PipeReader"/>. /// </summary> /// <param name="result">The <see cref="ReadResult"/></param> /// <returns>True if data was available, or if the call was canceled or the writer was completed.</returns> /// <remarks>If the pipe returns false, there's no need to call <see cref="AdvanceTo(SequencePosition, SequencePosition)"/>.</remarks> public abstract bool TryRead(out ReadResult result);
public override bool TryRead(out ReadResult result) { return(_pipe.TryRead(out result)); }
public override bool TryRead(out ReadResult result) { ThrowIfCompleted(); return(TryReadInternal(InternalTokenSource, out result)); }
public bool TryRead(out ReadResult result) { result = default; return(false); }