7

Related to asynchronous IO using a (bidirectional) NetworkStream, MSDN says that "EndRead must be called once for every call to BeginRead."

Is this true even for cases where the EndRead() will throw an exception, such as in the case that the NetworkStream has been closed after the BeginRead() has been issued?

I don't want the overhead of the throwing of the exception, but neither do I want to leak OS precious resources reserved by BeginRead().

I also know that the stream could be closed between a test of the stream's state and the conditional EndRead(), but if EndRead() can be omitted when we know the stream is closed, that will save on the exception handling in the majority case.

Am I doing it wrong?

Thanks!

Jason Kleban
  • 20,024
  • 18
  • 75
  • 125
  • What kind of performance hit are you actually seeing when you handle exceptions? – anton.burger Jun 24 '11 at 13:45
  • None that I can detect. But I have read and believe it to be true that while putting code in a try-catch block has minimal performance impact, that actually throwing an exception (which needs catching) is computationally expensive. It is recommended (somewhere) that exceptions should not be used to communicate results of normal operations - that checking for success criteria ahead of time can avoid or at least reduce exceptions. Exceptions should only be used in exceptional cases, not inevitable ones. – Jason Kleban Jun 24 '11 at 14:26
  • There are plenty of places in the .Net framework and other libraries where catching an exception is the only way. Also, because the state of a socket could change between checking for success criteria and executing a subsequent call (however slim a chance this may be) could still lead to an exception. But if it can be avoided, I'd like to know the most proper usage. – Jason Kleban Jun 24 '11 at 14:29
  • 1
    As Anton (the other one) suggests, "most proper" would be to call EndRead. If catching exceptions causes you an *actual* problem, then you might have to rethink something, possibly your choice of programming language :P As you say, there's no getting away from exceptions in the Framework. But I think you're trying to optimise too early. – anton.burger Jun 24 '11 at 15:47

1 Answers1

7

GCHandles pinning your buffers and some other unmanaged resources are released by the completion port callback. The unmanaged OVERLAPPED structure will hang around until the IAsyncResult gets finalized. This may be tolerable if the network load in your application is not large, but may become a problem if your application handles many connections per second, because finalization happens only after a full GC collection and on a separate thread.

NB: these are implementation details, obtained with Reflector. Caveat emptor.

Anton Tykhyy
  • 19,370
  • 5
  • 54
  • 56
  • 3
    Can't really say as I know nothing about your app, but I'd recommend calling `EndRead` unless you profile your app and find that the exception `EndRead` throws is causing significant performance losses. – Anton Tykhyy Jun 23 '11 at 13:36