/// <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 }