Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CancellationToken to TextReader.ReadXAsync #61898

Merged
merged 10 commits into from
Jan 25, 2022
Prev Previous commit
Next Next commit
Add XML documentation for new methods.
  • Loading branch information
bgrainger committed Jan 24, 2022
commit 79115473556b066f68a11ccf094f7e99e11c32af
50 changes: 50 additions & 0 deletions src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -848,6 +848,31 @@ private int ReadBuffer(Span<char> userBuffer, out bool readToUserBuffer)
public override Task<string?> ReadLineAsync() =>
ReadLineAsync(default).AsTask();

/// <summary>
/// Reads a line of characters asynchronously from the current stream and returns the data as a string.
/// </summary>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>A value task that represents the asynchronous read operation. The value of the <c>TResult</c>
/// parameter contains the next line from the stream, or is <c>null</c> if all of the characters have been read.</returns>
adamsitnik marked this conversation as resolved.
Show resolved Hide resolved
/// <exception cref="ArgumentOutOfRangeException">The number of characters in the next line is larger than <see cref="int.MaxValue"/>.</exception>
/// <exception cref="ObjectDisposedException">The stream reader has been disposed.</exception>
/// <exception cref="InvalidOperationException">The reader is currently in use by a previous read operation.</exception>
/// <example>
/// The following example shows how to read the first line of a file by using the <see cref="ReadLineAsync(CancellationToken)"/> method.
/// <code lang="C#">
/// using var tokenSource = new CancellationTokenSource();
/// using var reader = File.OpenText("existingfile.txt");
/// Console.WriteLine("Opened file.");
///
/// var result = await reader.ReadLineAsync(tokenSource.Token);
/// Console.WriteLine("First line contains: " + result);
adamsitnik marked this conversation as resolved.
Show resolved Hide resolved
/// </code>
/// </example>
/// <remarks>
/// <para>If this method is canceled via <paramref name="cancellationToken"/>, some data
/// that has been read from the current <see cref="Stream"/> but not stored (by the
/// <see cref="StreamReader"/>) or returned (to the caller) may be lost.</para>
adamsitnik marked this conversation as resolved.
Show resolved Hide resolved
/// </remarks>
public override ValueTask<string?> ReadLineAsync(CancellationToken cancellationToken)
{
// If we have been inherited into a subclass, the following implementation could be incorrect
Expand Down Expand Up @@ -931,6 +956,31 @@ private int ReadBuffer(Span<char> userBuffer, out bool readToUserBuffer)

public override Task<string> ReadToEndAsync() => ReadToEndAsync(default);

/// <summary>
/// Reads all characters from the current position to the end of the stream asynchronously and returns them as one string.
/// </summary>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>A task that represents the asynchronous read operation. The value of the <c>TResult</c> parameter contains
/// a string with the characters from the current position to the end of the stream.</returns>
/// <exception cref="ArgumentOutOfRangeException">The number of characters is larger than <see cref="int.MaxValue"/>.</exception>
/// <exception cref="ObjectDisposedException">The stream reader has been disposed.</exception>
/// <exception cref="InvalidOperationException">The reader is currently in use by a previous read operation.</exception>
/// <example>
/// The following example shows how to read the contents of a file by using the <see cref="ReadToEndAsync(CancellationToken)"/> method.
/// <code lang="C#">
/// using var tokenSource = new CancellationTokenSource();
/// using var reader = File.OpenText("existingfile.txt");
/// Console.WriteLine("Opened file.");
///
/// var result = await reader.ReadToEndAsync(tokenSource.Token);
/// Console.WriteLine("Contains: " + result);
adamsitnik marked this conversation as resolved.
Show resolved Hide resolved
/// </code>
/// </example>
/// <remarks>
/// <para>If this method is canceled via <paramref name="cancellationToken"/>, some data
/// that has been read from the current <see cref="Stream"/> but not stored (by the
/// <see cref="StreamReader"/>) or returned (to the caller) may be lost.</para>
adamsitnik marked this conversation as resolved.
Show resolved Hide resolved
/// </remarks>
public override Task<string> ReadToEndAsync(CancellationToken cancellationToken)
{
// If we have been inherited into a subclass, the following implementation could be incorrect
Expand Down
53 changes: 53 additions & 0 deletions src/libraries/System.Private.CoreLib/src/System/IO/StringReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,34 @@ public override string ReadToEnd()
return Task.FromResult(ReadLine());
}

/// <summary>
/// Reads a line of characters asynchronously from the current string and returns the data as a string.
/// </summary>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>A value task that represents the asynchronous read operation. The value of the <c>TResult</c>
/// parameter contains the next line from the string reader, or is <c>null</c> if all of the characters have been read.</returns>
adamsitnik marked this conversation as resolved.
Show resolved Hide resolved
/// <exception cref="ArgumentOutOfRangeException">The number of characters in the next line is larger than <see cref="int.MaxValue"/>.</exception>
/// <exception cref="ObjectDisposedException">The string reader has been disposed.</exception>
/// <exception cref="InvalidOperationException">The reader is currently in use by a previous read operation.</exception>
/// <example>
/// The following example shows how to read one line at a time from a string asynchronously.
/// <code lang="C#">
/// using System.Text;
///
/// StringBuilder stringToRead = new();
/// stringToRead.AppendLine("Characters in 1st line to read");
/// stringToRead.AppendLine("and 2nd line");
/// stringToRead.AppendLine("and the end");
///
/// string readText;
/// using var tokenSource = new CancellationTokenSource();
/// using var reader = new StringReader(stringToRead.ToString());
adamsitnik marked this conversation as resolved.
Show resolved Hide resolved
/// while ((readText = await reader.ReadLineAsync(tokenSource.Token)) is not null)
/// {
/// Console.WriteLine(readText);
/// }
/// </code>
/// </example>
public override ValueTask<string?> ReadLineAsync(CancellationToken cancellationToken) =>
cancellationToken.IsCancellationRequested
? ValueTask.FromCanceled<string?>(cancellationToken)
Expand All @@ -234,6 +262,31 @@ public override Task<string> ReadToEndAsync()
return Task.FromResult(ReadToEnd());
}

/// <summary>
/// Reads all characters from the current position to the end of the string asynchronously and returns them as a single string.
/// </summary>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>A task that represents the asynchronous read operation. The value of the <c>TResult</c> parameter contains
/// a string with the characters from the current position to the end of the string.</returns>
/// <exception cref="ArgumentOutOfRangeException">The number of characters is larger than <see cref="int.MaxValue"/>.</exception>
/// <exception cref="ObjectDisposedException">The string reader has been disposed.</exception>
/// <exception cref="InvalidOperationException">The reader is currently in use by a previous read operation.</exception>
/// <example>
/// The following example shows how to read an entire string asynchronously.
/// <code lang="C#">
/// using System.Text;
///
/// StringBuilder stringToRead = new();
/// stringToRead.AppendLine("Characters in 1st line to read");
/// stringToRead.AppendLine("and 2nd line");
/// stringToRead.AppendLine("and the end");
///
/// using var tokenSource = new CancellationTokenSource();
/// using var reader = new StringReader(stringToRead.ToString());
adamsitnik marked this conversation as resolved.
Show resolved Hide resolved
/// var readText = await reader.ReadToEndAsync(tokenSource.Token);
/// Console.WriteLine(readText);
/// </code>
/// </example>
public override Task<string> ReadToEndAsync(CancellationToken cancellationToken) =>
cancellationToken.IsCancellationRequested
? Task.FromCanceled<string>(cancellationToken)
Expand Down
31 changes: 31 additions & 0 deletions src/libraries/System.Private.CoreLib/src/System/IO/TextReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,23 @@ public virtual int ReadBlock(Span<char> buffer)
#region Task based Async APIs
public virtual Task<string?> ReadLineAsync() => ReadLineCoreAsync(default);

/// <summary>
/// Reads a line of characters asynchronously and returns the data as a string.
/// </summary>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>A value task that represents the asynchronous read operation. The value of the <c>TResult</c>
/// parameter contains the next line from the text reader, or is <c>null</c> if all of the characters have been read.</returns>
adamsitnik marked this conversation as resolved.
Show resolved Hide resolved
/// <exception cref="ArgumentOutOfRangeException">The number of characters in the next line is larger than <see cref="int.MaxValue"/>.</exception>
/// <exception cref="ObjectDisposedException">The text reader has been disposed.</exception>
/// <exception cref="InvalidOperationException">The reader is currently in use by a previous read operation.</exception>
/// <remarks>
/// <para>The <see cref="TextReader"/> class is an abstract class. Therefore, you do not instantiate it in
/// your code. For an example of using the <see cref="ReadLineAsync(CancellationToken)"/> method, see the
/// <see cref="StreamReader.ReadLineAsync(CancellationToken)"/> method.</para>
/// <para>If the current <see cref="TextReader"/> represents the standard input stream returned by
/// the <c>Console.In</c> property, the <see cref="ReadLineAsync(CancellationToken)"/> method
adamsitnik marked this conversation as resolved.
Show resolved Hide resolved
/// executes synchronously rather than asynchronously.</para>
/// </remarks>
public virtual ValueTask<string?> ReadLineAsync(CancellationToken cancellationToken) =>
bgrainger marked this conversation as resolved.
Show resolved Hide resolved
new ValueTask<string?>(ReadLineCoreAsync(cancellationToken));

Expand All @@ -214,6 +231,20 @@ public virtual int ReadBlock(Span<char> buffer)

public virtual Task<string> ReadToEndAsync() => ReadToEndAsync(default);

/// <summary>
/// Reads all characters from the current position to the end of the text reader asynchronously and returns them as one string.
/// </summary>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>A task that represents the asynchronous read operation. The value of the <c>TResult</c> parameter contains
/// a string with the characters from the current position to the end of the text reader.</returns>
/// <exception cref="ArgumentOutOfRangeException">The number of characters is larger than <see cref="int.MaxValue"/>.</exception>
/// <exception cref="ObjectDisposedException">The text reader has been disposed.</exception>
/// <exception cref="InvalidOperationException">The reader is currently in use by a previous read operation.</exception>
/// <remarks>
/// <para>The <see cref="TextReader"/> class is an abstract class. Therefore, you do not instantiate it in
/// your code. For an example of using the <see cref="ReadToEndAsync(CancellationToken)"/> method, see the
/// <see cref="StreamReader.ReadToEndAsync(CancellationToken)"/> method.</para>
/// </remarks>
public virtual async Task<string> ReadToEndAsync(CancellationToken cancellationToken)
{
var sb = new StringBuilder(4096);
Expand Down