/// <summary>
        /// Writes the given text to the response body using the given encoding.
        /// </summary>
        /// <param name="response">The <see cref="HttpResponse"/>.</param>
        /// <param name="text">The text to write to the response.</param>
        /// <param name="encoding">The encoding to use.</param>
        /// <param name="cancellationToken">Notifies when request operations should be cancelled.</param>
        /// <returns>A task that represents the completion of the write operation.</returns>
        public static Task WriteAsync(this HttpResponse response, string text, Encoding encoding, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (response == null)
            {
                throw new ArgumentNullException(nameof(response));
            }

            if (text == null)
            {
                throw new ArgumentNullException(nameof(text));
            }

            if (encoding == null)
            {
                throw new ArgumentNullException(nameof(encoding));
            }

            // Need to call StartAsync before GetMemory/GetSpan
            if (!response.HasStarted)
            {
                var startAsyncTask = response.StartAsync(cancellationToken);
                if (!startAsyncTask.IsCompletedSuccessfully)
                {
                    return(StartAndWriteAsyncAwaited(response, text, encoding, cancellationToken, startAsyncTask));
                }
            }

            Write(response, text, encoding);

            var flushAsyncTask = response.BodyPipe.FlushAsync(cancellationToken);

            if (flushAsyncTask.IsCompletedSuccessfully)
            {
                // Most implementations of ValueTask reset state in GetResult, so call it before returning a completed task.
                flushAsyncTask.GetAwaiter().GetResult();
                return(Task.CompletedTask);
            }

            return(flushAsyncTask.AsTask());
        }