2
votes

I am relatively new to using the Async pattern for stream reading and writing, and wondered if the answer to this question is so obvious it is not written anywhere explicitly:

When calling a NetworkStream.BeginRead, I pass a callback parameter, which according to MSDN is executed "when BeginRead completes". It also says that "your callback method should call the EndRead method."

Then according to the documentation for NetworkStream.EndRead, the "method completes the asynchronous read operation started in the BeginRead method." It also mentions that this method "blocks until data is available."

I know the EndRead method is also useful for determining the number of bytes received.

My question is:

If the EndRead method is called within the BeginRead callback, does it ever really block? Isn't the read operation already complete when the callback is invoked?

Sample Code

    byte[] streamBuffer = new byte[1024];

    public void SomeFunction()
    {
        TcpClient client = new TcpClient();
        client.Connect(IPAddress.Parse("127.0.0.1"), 32000);

        NetworkStream stream = client.GetStream();

        stream.BeginRead(streamBuffer,0,streamBuffer.Length,ReadCallback,stream);
    }

    public void ReadCallback(IAsyncResult ar)
    {
        NetworkStream stream = ar.AsyncState as NetworkStream;

        // Will this call ever actually "block" or will it
        // return immediately? Isn't the read operation
        // already complete?
        int bytesRead = stream.EndRead(ar);

        // Other stuff here
    }
3
Please post some code. - spender

3 Answers

2
votes

The read operation is always completed when the callback fires. Completion is what gets the callback fired in the first place. So EndRead() will never block when it is used in the callback method.

Do note that "completed" can also mean "failed", EndRead() will throw the exception. A very common exception is ObjectDisposedException, thrown when the socket is closed while an asynchronous read is in progress. Typical when you exit your program, be sure to catch it.

1
votes

You can use EndRead in two situations:

  • You can use EndRead in your call back functions. At this point nothing will be blocked.
  • You can also use EndRead without the call back function:

    myStream.BeginRead(...);
    // Do a lot of work at the same time.
    // When my work is done, wait for the stream to finish its work.
    myStream.EndRead(...);

EndRead should always be called to report some errors have occured. If an error has occured, an EndRead will throw an exception.

0
votes

No, because the EndRead method is being called (and blocking) within the delegate which is being called asynchronously. So yes, the method with EndRead is blocking, but not on the thread of execution that called BeginRead.