-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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 async overloads to BinaryReader/Writer #17229
Comments
To clarify, you mean every write/read method yes? So if you create a BinaryReader/Writer around a stream you can call To do that we'd need to call the underlying stream's Then I suppose we'd want to consider adding cancellation token overloads. So to write a double you could do either:
|
Yep!
Yep! |
We need API proposal. |
We also need a plan for how it should behave in the case of the async overload being called on a derived class. |
@ronnieoverby Nice code. Unfortunately, there's no license information anywhere, so the project cannot be used legally anywhere :-( |
@markusschaber DOH! Thanks. Added MIT LICENSE. |
@ronnieoverby Thanks a lot! :-) |
@ronnieoverby Great job! and is it support .net core? |
@h82258652 yes, it's a .NET standard library, so core/framework support. |
@ronnieoverby Thank you. |
Is this something that would still be beneficial for the /cc: @davidfowl / @Drawaes |
Async overloads to |
API proposalAdd async overloads to BinaryReadernamespace System.IO
{
public partial class BinaryReader : System.IDisposable
{
public virtual ValueTask<int> ReadAsync(CancellationToken cancellationToken = default);
public virtual ValueTask<int> ReadAsync(byte[] buffer, int index, int count, CancellationToken cancellationToken = default);
public virtual ValueTask<int> ReadAsync(char[] buffer, int index, int count, CancellationToken cancellationToken = default);
public virtual ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default);
public virtual ValueTask<int> ReadAsync(Memory<char> buffer, CancellationToken cancellationToken = default);
public virtual ValueTask<bool> ReadBooleanAsync(CancellationToken cancellationToken = default);
public virtual ValueTask<byte> ReadByteAsync(CancellationToken cancellationToken = default);
public virtual ValueTask<byte[]> ReadBytesAsync(int count, CancellationToken cancellationToken = default);
public virtual ValueTask<char> ReadCharAsync(CancellationToken cancellationToken = default);
public virtual ValueTask<char[]> ReadCharsAsync(int count, CancellationToken cancellationToken = default);
public virtual ValueTask<decimal> ReadDecimalAsync(CancellationToken cancellationToken = default);
public virtual ValueTask<double> ReadDoubleAsync(CancellationToken cancellationToken = default);
public virtual ValueTask<short> ReadInt16Async(CancellationToken cancellationToken = default);
public virtual ValueTask<int> ReadInt32Async(CancellationToken cancellationToken = default);
public virtual ValueTask<long> ReadInt64Async(CancellationToken cancellationToken = default);
[CLSCompliantAttribute(false)]
public virtual ValueTask<sbyte> ReadSByteAsync(CancellationToken cancellationToken = default);
public virtual ValueTask<float> ReadSingleAsync(CancellationToken cancellationToken = default);
public virtual ValueTask<string> ReadStringAsync(CancellationToken cancellationToken = default);
[CLSCompliantAttribute(false)]
public virtual ValueTask<ushort> ReadUInt16Async(CancellationToken cancellationToken = default);
[CLSCompliantAttribute(false)]
public virtual ValueTask<uint> ReadUInt32Async(CancellationToken cancellationToken = default);
[CLSCompliantAttribute(false)]
public virtual ValueTask<ulong> ReadUInt64Async(CancellationToken cancellationToken = default);
public virtual ValueTask<int> PeekCharAsync(CancellationToken cancellationToken = default);
protected internal ValueTask<int> Read7BitEncodedIntAsync(CancellationToken cancellationToken = default);
protected virtual ValueTask FillBufferAsync(int numBytes, CancellationToken cancellationToken = default);
}
} BinaryWriternamespace System.IO
{
public partial class BinaryWriter : IAsyncDisposable, IDisposable
{
public virtual ValueTask FlushAsync(CancellationToken cancellationToken = default);
public virtual ValueTask WriteAsync(bool value, CancellationToken cancellationToken = default);
public virtual ValueTask WriteAsync(byte value, CancellationToken cancellationToken = default);
public virtual ValueTask WriteAsync(byte[] buffer, CancellationToken cancellationToken = default);
public virtual ValueTask WriteAsync(byte[] buffer, int index, int count, CancellationToken cancellationToken = default);
public virtual ValueTask WriteAsync(char ch, CancellationToken cancellationToken = default);
public virtual ValueTask WriteAsync(char[] chars, CancellationToken cancellationToken = default);
public virtual ValueTask WriteAsync(char[] chars, int index, int count, CancellationToken cancellationToken = default);
public virtual ValueTask WriteAsync(decimal value, CancellationToken cancellationToken = default);
public virtual ValueTask WriteAsync(double value, CancellationToken cancellationToken = default);
public virtual ValueTask WriteAsync(short value, CancellationToken cancellationToken = default);
public virtual ValueTask WriteAsync(int value, CancellationToken cancellationToken = default);
public virtual ValueTask WriteAsync(long value, CancellationToken cancellationToken = default);
public virtual ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default);
public virtual ValueTask WriteAsync(ReadOnlyMemory<char> chars, CancellationToken cancellationToken = default);
[CLSCompliantAttribute(false)]
public virtual ValueTask WriteAsync(sbyte value, CancellationToken cancellationToken = default);
public virtual ValueTask WriteAsync(float value, CancellationToken cancellationToken = default);
public virtual ValueTask WriteAsync(string value, CancellationToken cancellationToken = default);
[CLSCompliantAttribute(false)]
public virtual ValueTask WriteAsync(ushort value, CancellationToken cancellationToken = default);
[CLSCompliantAttribute(false)]
public virtual ValueTask WriteAsync(uint value, CancellationToken cancellationToken = default);
[CLSCompliantAttribute(false)]
public virtual ValueTask WriteAsync(ulong value, CancellationToken cancellationToken = default);
protected void Write7BitEncodedInt(int value) { }
protected ValueTask Write7BitEncodedIntAsync(int value, CancellationToken cancellationToken = default);
}
} StreamAssociated byte-level async read/write methods for the Stream API. public abstract partial class Stream : MarshalByRefObject, IAsyncDisposable, IDisposable
{
public virtual ValueTask<int> ReadByteAsync(CancellationToken cancellationToken = default);
public virtual ValueTask WriteByteAsync(byte value, CancellationToken cancellationToken = default);
} |
public virtual ValueTask<int> ReadAsync(byte[] buffer, int index, int count, CancellationToken cancellationToken = default);
public virtual ValueTask<int> ReadAsync(char[] buffer, int index, int count, CancellationToken cancellationToken = default);
public virtual ValueTask WriteAsync(byte[] buffer, CancellationToken cancellationToken = default);
public virtual ValueTask WriteAsync(byte[] buffer, int index, int count, CancellationToken cancellationToken = default);
public virtual ValueTask WriteAsync(char[] chars, CancellationToken cancellationToken = default);
public virtual ValueTask WriteAsync(char[] chars, int index, int count, CancellationToken cancellationToken = default); Is there a reason to have these array-based overloads, when |
Yes, to avoid the performance and memory costs of creating |
@manandre What costs? |
@svick I agree, but in the Stream API context, the array-based methods are generally the legacy and more optimized ones, while the |
We're talking about brand new APIs, so I think legacy implementations are irrelevant.
Yes: it makes the API simpler. And it shouldn't hurt API clients much, since |
Here I do not talk of the new BinaryReader/Writer API, but the existing Stream one, i.e the API of the output stream given as parameter at construction time. And I make the strong hypothesis that array-based methods (resp.
I consider that using |
Unless the underlying Stream explicitly has overrides for the If the Stream is not Memory aware, its very inefficient due to the api evolution. As a user of the api you'd probably be be using Memory with Memory aware streams; but if you are using arrays, then there is a significant chance you are also using it with Streams that are not Memory aware, |
If the
Really? All of the Streams in .NET Core that matter override these (if you find one that doesn't in a case where perf matters, please open an issue). And I'd be willing to bet that the majority of Stream uses are of these built-in stream types. |
@stephentoub So, do you also recommend to skip the array-based overloads from the API proposal? |
@carlossanlop @davidfowl Can we get this API proposal reviewed as it and let reviewers decide whether to keep or remove these array-based overloads? |
While we are waiting for a new API, I've found NuGet Package with this functionality: https://github.com/ronnieoverby/AsyncBinaryReaderWriter Would check how good it is in the following days. Looks promising. |
Just let me know if you find any issues. |
@carlossanlop Is there something holding this issue in the |
Wouldn't it be a better idea to discard the binary reader and implement its methods as extension method on Stream? |
@lanwin I think it is not possible, because BinaryReader/Writer holds some state. We could pass the parameters to every call to the static method (for the Writer only. For the Reader I think it is not possible since it contains buffers), but I think that is inconvenient, and BinaryReader/Writer also allows inherited classes to override its methods, what wouldn't be possible with extension methods. |
Greetings all. What is the technical hold up on this feature request? |
Because I'd love to use it to read/write things, asynchronously from the network.
Edit: API Proposal can be found here.
The text was updated successfully, but these errors were encountered: