Skip to content

[API Proposal]: Add CancellationToken to TextWriter.FlushAsync #64340

@Shane32

Description

@Shane32

Background and motivation

Some TextWriter implementations such as StreamWriter serve to encode data in a particular format and then write that data to an underlying data stream. The underlying data stream could easily be a file stream or network stream, where it is desired to be able to cancel any pending operation upon either an upstream cancellation (e.g. termination of the HTTP request that initiated such as data transfer) or user request (e.g. user clicks Cancel button).

Some implementations also buffer data before reaching the underlying stream, and without a call to Flush (or AutoFlush = true), do not flush those buffers to the underlying stream. So it is sometimes necessary in these instances to call Flush to ensure that the TextWriter implementation has flushed its buffers to the underlying stream, even if it is not necessary to flush the underlying stream. Typical implementations of Flush however will typically flush their own buffers and then call the Flush method of the underlying stream.

Calling FlushAsync on an underlying data stream can often result in an asynchronous delay while the data is written to disk or sent over the network. However, the method does not provide any means to cancel the underlying write/flush operation.

With the merging of #61898, both TextReader and TextWriter supports cancellation tokens for each of their methods (in some form) except this one.

Note that the Stream.FlushAsync method has an overload with a cancellation token since .NET Standard 1.0, so there is underlying support for the means to asynchronously flush buffers to disk/network as described in the example above.

API Proposal

public abstract class TextWriter : MarshalByRefObject, IAsyncDisposable, IDisposable
{
    public virtual System.Threading.Tasks.Task FlushAsync (CancellationToken cancellationToken);
}

API Usage

async Task PrintReportAsync(TextWriter writer, CancellationToken cancellationToken = default)
{
    await writer.WriteLineAsync("Some data".AsMemory(), cancellationToken);
    await writer.FlushAsync(cancellationToken);
}

Alternative Designs

Alternatively, ValueTask could be used, but based on the other APIs that do not return a value, it would seem that Task is preferred here.

public abstract class TextWriter : MarshalByRefObject, IAsyncDisposable, IDisposable
{
    public virtual System.Threading.Tasks.ValueTask FlushAsync (CancellationToken cancellationToken);
}

Risks

No response

References

Metadata

Metadata

Assignees

Labels

api-approvedAPI was approved in API review, it can be implementedarea-System.IO

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions