Runtime: Documentation needed:System.IO.Pipelines.PipeWriter.FlushAsync cancellation represenatation

Created on 3 Jul 2020  路  4Comments  路  Source: dotnet/runtime

When System.IO.Pipelines.PipeWriter.FlushAsync has been canceled,We could retrieve info about it was canceled.

But it seems that there is two way to represent it was canceled.

  1. Set FlushResult.IsCanceled to true.

  2. Throws OperationCanceledException.

I couldn't find out why there is two way to represent it.
I think that there is two solution.

  1. Remove FlushResult.IsCanceled property,and we always throw OperationCanceledException on canceled.

  2. Note obviously how ,and why we should distinguish two representations (on MSDN).

area-System.IO.Pipelines documentation

Most helpful comment

Any change to always throw an OperationCanceledException would be breaking and would have serious performance implications, so I doubt that's in the cards. The documentation should definitely be improved though.

To clarify things in the meantime, here's how it works:

  1. If FlushResult.IsCanceled is true, someone called PipeWriter.CancelPendingFlush(). Period.

    • Similarly if ReadResult.IsCanceled is true, someone called PipeReader.CancelPendingRead()

    • There is no other reason either IsCanceled property can be true short of a weirdly-behaving custom PipeWriter/PipeReader implementation

  2. If FlushAsync throws and OperationCanceledException, it means one of two things:

    1. The CancellationToken passed to FlushAsync was canceled.

    2. PipeReader.Complete(Exception) was called with an OperationCanceledException

    3. As with IsCanceled, FlushAsync and ReadAsync have analogous behavior wrt OperationCanceledExceptions.

Why support CancelPendingFlush() and CancellationTokens? CancelPendingFlush() is the more efficient way to cancel writes since every FlushAsync operation doesn't have to register with a CancellationToken if CancelPendingFlush() is used instead. However, CancellationToken support is still desirable when using Pipes to implement another API that supports CancellationToken like Stream.

All 4 comments

IMHO, throwing OperationCanceledException means it was canceled unexpectedly (it is an exception at all), while the other means it was canceled by user or something like that. And it must be obvious enough.

IMHO, throwing OperationCanceledException means it was canceled unexpectedly (it is an exception at all), while the other means it was canceled by user or something like that. And it must be obvious enough.

You are partially right."Exception" should be exceptional.
But "OperationCanceledException" is exception of "Exception".
We usually treats it faulted if Task throws exception,But if it was OperationCanceledException,we treats it canceled.
If it was canceled unexpectedly,We should throw exception which represents why it was canceled.(e.g. IOException)

Thank you for teaching!
Now, I feel certain that it should be documented for people who don't understand it like me :grin:.

Any change to always throw an OperationCanceledException would be breaking and would have serious performance implications, so I doubt that's in the cards. The documentation should definitely be improved though.

To clarify things in the meantime, here's how it works:

  1. If FlushResult.IsCanceled is true, someone called PipeWriter.CancelPendingFlush(). Period.

    • Similarly if ReadResult.IsCanceled is true, someone called PipeReader.CancelPendingRead()

    • There is no other reason either IsCanceled property can be true short of a weirdly-behaving custom PipeWriter/PipeReader implementation

  2. If FlushAsync throws and OperationCanceledException, it means one of two things:

    1. The CancellationToken passed to FlushAsync was canceled.

    2. PipeReader.Complete(Exception) was called with an OperationCanceledException

    3. As with IsCanceled, FlushAsync and ReadAsync have analogous behavior wrt OperationCanceledExceptions.

Why support CancelPendingFlush() and CancellationTokens? CancelPendingFlush() is the more efficient way to cancel writes since every FlushAsync operation doesn't have to register with a CancellationToken if CancelPendingFlush() is used instead. However, CancellationToken support is still desirable when using Pipes to implement another API that supports CancellationToken like Stream.

Was this page helpful?
0 / 5 - 0 ratings