Answered Reporting documentation errors

All Replies

  • Monday, July 23, 2012 2:11 PM
     
     

    Correction: could be a doc bug or a behavior bug.

    In particular, if a block's CancellationToken is canceled, "await ReceiveAsync" will not throw OperationCanceledException. It throws InvalidOperationException instead.

    This makes it impossible for the code calling ReceiveAsync to distinguish between a clean completion and an aborted completion.

           -Steve


    Programming blog: http://nitoprograms.blogspot.com/
      Including my TCP/IP .NET Sockets FAQ
      and How to Implement IDisposable and Finalizers: 3 Easy Rules
    Microsoft Certified Professional Developer

    How to get to Heaven according to the Bible

  • Monday, July 23, 2012 3:16 PM
    Owner
     
     Answered

    Hi Steve-

    The issue you're seeing is when passing the CancellationToken both to ReceiveAsync and to the block being received from, right?  If you just pass the token to the block, and not to ReceiveAsync, then a faulted task with an InvalidOperationException is expected here, because ReceiveAsync was told to wait for data which will never arrive.  If you pass the token to ReceiveAsync and not to the block, then a canceled task is expected here, because you're canceling the ReceiveAsync operation.  If you pass the token to both, then there's a race as to which condition will be noticed first, so you could get an InvalidOperationException.  While technically by design, the team is looking at it to determine whether there's a better solution; we already have a bug filed on this internally.

    Regardless, as you point out, the documentation for ReceiveAsync is wrong, as it neglects to call out the faulting case if the source completes without data.  We'll get that fixed.

    Thanks!

  • Monday, July 23, 2012 11:22 PM
     
     

    Actually, I was just passing the CancellationToken to a BufferBlock, not to ReceiveAsync (for this test).

    The docs suggest I'd get an OperationCanceledException (presumably with a default CancellationToken) if the buffer is completed:

    If an item cannot be retrieved, either because cancellation is requested or the source is empty and completed, the returned task will be canceled.

    It doesn't really matter to me, as long as it's documented and consistent. The race condition situation you mentioned isn't ideal, since I will have situations where I'll be passing the same CancellationToken to the block and ReceiveAsync. Also, I'm not a big fan of having to handle InvalidOperationException at all; IOE can mean a lot of different things.

           -Steve


    Programming blog: http://nitoprograms.blogspot.com/
      Including my TCP/IP .NET Sockets FAQ
      and How to Implement IDisposable and Finalizers: 3 Easy Rules
    Microsoft Certified Professional Developer

    How to get to Heaven according to the Bible