/// <summary>
        /// Asynchronously clears all buffers for a stream and causes any buffered data to be written to the underlying device,
        /// and monitors cancellation requests.
        /// </summary>
        /// <remarks>
        /// <para>If the operation is canceled before it completes, the returned task contains the <see cref="TaskStatus.Canceled"/>
        /// value for the <see cref="Task.Status"/> property.</para>
        /// <para>
        /// If a derived class does not flush the buffer in its implementation of the <see cref="Stream.Flush()"/> method,
        /// the <see cref="FlushAsync(Stream)"/> method will not flush the buffer.
        /// </para>
        /// </remarks>
        /// <param name="stream">The stream to flush.</param>
        /// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None"/>.</param>
        /// <returns>A task that represents the asynchronous flush operation.</returns>
        /// <exception cref="ArgumentNullException">If <paramref name="stream"/> is <see langword="null"/>.</exception>
        /// <exception cref="ObjectDisposedException">If <paramref name="stream"/> has been disposed.</exception>
        public static Task FlushAsync(this Stream stream, CancellationToken cancellationToken)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }

            if (cancellationToken.IsCancellationRequested)
            {
                return(CompletedTask.Canceled());
            }

#if NET45PLUS
            // This code requires the `Stream` class provide an implementation of `FlushAsync`. The unit tests will
            // detect any case where this results in a stack overflow.
            return(stream.FlushAsync(cancellationToken));
#else
            return(Task.Factory.StartNew(state => ((Stream)state).Flush(), stream, cancellationToken, TaskCreationOptions.None, TaskScheduler.Default));
#endif
        }
        /// <summary>
        /// Asynchronously writes a sequence of bytes to a stream, advances the position within the stream by the number of bytes written,
        /// and monitors cancellation requests.
        /// </summary>
        /// <remarks>
        /// <para>Use the <see cref="Stream.CanWrite"/> property to determine whether the stream instance supports writing.</para>
        /// <para>
        /// If the operation is canceled before it completes, the returned task contains the <see cref="TaskStatus.Canceled"/>
        /// value for the <see cref="Task.Status"/> property.
        /// </para>
        /// </remarks>
        /// <param name="stream">The stream to write data to.</param>
        /// <param name="buffer">The buffer to read the data from.</param>
        /// <param name="offset">The zero-based byte offset in buffer from which to begin copying bytes to the stream.</param>
        /// <param name="count">The maximum number of bytes to write.</param>
        /// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None"/>.</param>
        /// <returns>
        /// A task that represents the asynchronous write operation.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// <para>If <paramref name="stream"/> is <see langword="null"/>.</para>
        /// <para>-or-</para>
        /// <para>If <paramref name="buffer"/> is <see langword="null"/>.</para>
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        /// <para>If <paramref name="offset"/> is negative.</para>
        /// <para>-or-</para>
        /// <para>If <paramref name="count"/> is negative.</para>
        /// </exception>
        /// <exception cref="ArgumentException">
        /// <para>If the sum of <paramref name="offset"/> and <paramref name="count"/> is larger than the buffer length.</para>
        /// </exception>
        /// <exception cref="NotSupportedException">
        /// <para>If <paramref name="stream"/> does not support writing.</para>
        /// </exception>
        /// <exception cref="ObjectDisposedException">
        /// <para>If <paramref name="stream"/> has been disposed.</para>
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// <para>If <paramref name="stream"/> is currently in use by a previous write operation.</para>
        /// </exception>
        public static Task WriteAsync(this Stream stream, byte[] buffer, int offset, int count, CancellationToken cancellationToken)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }

            if (cancellationToken.IsCancellationRequested)
            {
                return(CompletedTask.Canceled());
            }

#if NET45PLUS
            // This code requires the `Stream` class provide an implementation of `WriteAsync`. The unit tests will
            // detect any case where this results in a stack overflow.
            return(stream.WriteAsync(buffer, offset, count, cancellationToken));
#else
            return(Task.Factory.FromAsync(stream.BeginWrite, stream.EndWrite, buffer, offset, count, null));
#endif
        }
        /// <summary>
        /// Asynchronously reads the bytes from a source stream and writes them to a destination stream,
        /// using a specified buffer size and cancellation token.
        /// </summary>
        /// <remarks>
        /// <para>If the operation is canceled before it completes, the returned task contains the <see cref="TaskStatus.Canceled"/>
        /// value for the <see cref="Task.Status"/> property.</para>
        /// <para>
        /// Copying begins at the current position in <paramref name="stream"/>.
        /// </para>
        /// </remarks>
        /// <param name="stream">The source stream.</param>
        /// <param name="destination">The stream to which the contents of the source stream will be copied.</param>
        /// <param name="bufferSize">The size, in bytes, of the buffer. This value must be greater than zero. The default size is 81920.</param>
        /// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None"/>.</param>
        /// <returns>A task that represents the asynchronous copy operation.</returns>
        /// <exception cref="ArgumentNullException">
        /// <para>If <paramref name="stream"/> is <see langword="null"/>.</para>
        /// <para>-or-</para>
        /// <para>If <paramref name="destination"/> is <see langword="null"/>.</para>
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        /// <para>If <paramref name="bufferSize"/> is negative or zero.</para>
        /// </exception>
        /// <exception cref="ObjectDisposedException">
        /// <para>If <paramref name="stream"/> is disposed.</para>
        /// <para>-or-</para>
        /// <para>If <paramref name="destination"/> is disposed.</para>
        /// </exception>
        /// <exception cref="NotSupportedException">
        /// <para>If <paramref name="stream"/> does not support reading.</para>
        /// <para>-or-</para>
        /// <para>If <paramref name="destination"/> does not support writing.</para>
        /// </exception>
        public static Task CopyToAsync(this Stream stream, Stream destination, int bufferSize, CancellationToken cancellationToken)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }
            if (destination == null)
            {
                throw new ArgumentNullException("destination");
            }
            if (!stream.CanRead)
            {
                throw new NotSupportedException("The stream does not support reading");
            }
            if (!destination.CanWrite)
            {
                throw new NotSupportedException("The destination does not support writing");
            }
            if (bufferSize <= 0)
            {
                throw new ArgumentOutOfRangeException("bufferSize");
            }

            if (cancellationToken.IsCancellationRequested)
            {
                return(CompletedTask.Canceled());
            }

#if NET45PLUS
            // This code requires the `Stream` class provide an implementation of `CopyToAsync`. The unit tests will
            // detect any case where this results in a stack overflow.
            return(stream.CopyToAsync(destination, bufferSize, cancellationToken));
#else
            return(CopyToAsync(stream, destination, new byte[bufferSize], cancellationToken));
#endif
        }