-
Notifications
You must be signed in to change notification settings - Fork 4.5k
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
[API Proposal]: Implement IAsyncDisposable on TextReader
#88244
Comments
Tagging subscribers to this area: @dotnet/area-system-io Issue DetailsBackground and motivationBy default, when disposing a API Proposalnamespace System.IO;
// new
public abstract partial class TextReader : MarshalByRefObject, IDisposable, IAsyncDisposable
{
public virtual ValueTask DisposeAsync();
}
// existing
public abstract partial class TextWriter : MarshalByRefObject, IDisposable, IAsyncDisposable
{
public virtual ValueTask DisposeAsync();
}
// new
public partial class StreamReader : TextReader
{
public override ValueTask DisposeAsync();
}
// existing
public partial class StreamWriter : TextWriter
{
public override ValueTask DisposeAsync();
} API Usageawait using var reader = new StreamReader(myAsyncStream); Alternative DesignsNo response RisksNo response
|
TextReader
and TextWriter
TextReader
Hi @Neme12 Thank you for your proposal. It sounds very reasonable to me, so I've marked it as ready for review. It should get reviewed by our API Review Board within few weeks. |
namespace System.IO;
public partial class TextReader
{
public virtual ValueTask DisposeAsync();
}
public partial class StreamReader : TextReader
{
public override ValueTask DisposeAsync();
} |
I would like to take care of this |
@dersia Sounds great, assigned to you. Note: main will soon be a .NET 9 branch. |
@Neme12 it took me some time to set everything up and I started the implementation. Edit: Also the Writer is never set to If you could clarify these points for me or tell me how to handle those changes, I can finish the work and sumbit the pull request. // @stephentoub |
@dersia I'm not a member of .NET or even a contributor here, I'm just a random person who discovered an issue, you might want to ask someone else :D |
You already have a PR for this? Or what review team? Just curious |
May be @adamsitnik or @stephentoub can help? see comment #88244 (comment) |
If what you mean by that is that it should call the synchronous |
@dersia that's a good question, moving the CheckAsyncTaskInProgresss() before the You should try to circumvent these issues if possible. cc @stephentoub |
@Jozkee for now I have just mirrored what StreamWriter does. |
CheckAsyncTaskInProgress will only throw if the StreamWriter is misused; behavior here is undefined. If it is misused and you're in this situation, there really isn't a right answer for what to do. If you move it to before the try block, then most likely it still won't be flushed and instead of determinstically closing the handle in response to Dispose, it'll just get non-deterministically closed when the handle is eventually finalized, still without the data being flushed first. I don't see a good reason to change anything here. |
I updated #89477 (comment) with a note that we should hold off on merging this feature in until .NET 9. @dersia / @Neme12 -- As part of my consideration for that conclusion, I watched the API Review video and read through this issue/comments. I want to make sure I'm not overlooking a scenario where this would be highly valuable. Can you share more about your scenarios where an async dispose during read will be helpful (beyond having API consistency with writing)? What type of async functionality would you like to have inside an async disposal? Thanks! |
@jeffhandley It's not about consistency with writing. It's when you have a |
Generally such async I/O happens as part of writing, which is why this was added to TextWriter and StreamWriter as well. Stream.Dispose for streams from which you're only reading typically doesn't do I/O. Can you share what scenario you have where you're using a TextReader to read from Stream that will do I/O as part of its disposal? |
If you have a |
Thanks. Is that a hypothetical or could you put us to some examples in code where that happens? It'd be helpful to see. |
I mean I assume that when I get a stream via using var client = new HttpClient();
await using var stream = await client.GetStreamAsync(url); |
It does not. |
Why doesn't it do so? |
Because Disconnect{Async} is about being able to reuse the same socket handle again for another connection. It's not relevant here. |
Why does it then have a |
You generally don't. It's basically just Shutdown at that point (in fact the Unix implementation just calls Shutdown). The .NET API has it because the winsock DisconnectEx has it. |
Regardless, from your comments / questions this all still sounds theoretical and that you don't actually have a known case where asynchronous work would be performed in a DisposeAsync on a Stream you're using underneath TextReader? |
I guess I don't then if the |
@stephentoub - I was looking at picking this up to implement but I see you removed the "good first issue" and "help wanted" labels. Is this issue no longer looking for help on it? |
Thanks, @AndyBevan. I removed the label because I'm still not convinced this is a necessary addition. Do you have an example case where it would be beneficial? |
Hi @stephentoub - No I don't think I do have an example, I was looking at this as something to help out on but after re-reviewing the thread it sounds like this code change is no longer needed - I'll look for something else. Thanks for getting back to me. |
@stephentoub I'm sorry, I assumed the disposal of the stream would be asynchronous in the example I provided:
I should have tried looking into the implementation details before opening this issue. However, I'd still argue there is value in this, since whether or not the returned stream in this case supports asynchronous disposal is indeed an implementation detail that I cannot infer by looking at the API, and that could in theory change in the future. The same is true for many other streams that come from various APIs. |
Background and motivation
By default, when disposing a
StreamReader
orStreamWriter
, the underlyingStream
itself is disposed. SinceStream
supports async disposal viaIAsyncDisposable
, bothStreamReader
andStreamWriter
should implementIAsyncDisposable
as well to support the case when the underlying stream supports it. Currently, onlyStreamWriter
implementsIAsyncDisposable
whileStreamReader
doesn't, so when usingStreamReader
, it's only possible to dispose the underlying stream synchronously.API Proposal
API Usage
Alternative Designs
No response
Risks
No response
The text was updated successfully, but these errors were encountered: