public Task FlushAsync(IHttpOutputProducer outputProducer, CancellationToken cancellationToken)
        {
            lock (_writeLock)
            {
                if (_completed)
                {
                    return(Task.CompletedTask);
                }

                return(_flusher.FlushAsync(0, outputProducer, cancellationToken));
            }
        }
        private async Task TimeFlushAsync(long count, IHttpOutputProducer outputProducer, CancellationToken cancellationToken)
        {
            _timeoutControl.StartTimingWrite(count);

            try
            {
                await _lastFlushTask;
            }
            catch (OperationCanceledException ex)
            {
                outputProducer.Abort(new ConnectionAbortedException(CoreStrings.ConnectionOrStreamAbortedByCancellationToken, ex));
            }
            catch
            {
                // A canceled token is the only reason flush should ever throw.
            }

            _timeoutControl.StopTimingWrite();

            cancellationToken.ThrowIfCancellationRequested();
        }
        public Task FlushAsync(long count = 0, IHttpOutputProducer outputProducer = null, CancellationToken cancellationToken = default)
        {
            var flushValueTask = _writer.FlushAsync(cancellationToken);

            if (flushValueTask.IsCompletedSuccessfully)
            {
                return(Task.CompletedTask);
            }

            // https://github.com/dotnet/corefxlab/issues/1334
            // Pipelines don't support multiple awaiters on flush.
            // While it's acceptable to call PipeWriter.FlushAsync again before the last FlushAsync completes,
            // it is not acceptable to attach a new continuation (via await, AsTask(), etc..). In this case,
            // we find previous flush Task which still accounts for any newly committed bytes and await that.
            lock (_flushLock)
            {
                if (_lastFlushTask.IsCompleted)
                {
                    _lastFlushTask = flushValueTask.AsTask();
                }

                return(TimeFlushAsync(count, outputProducer, cancellationToken));
            }
        }