Difference between NetworkStream.Read() and NetworkStream.BeginRead()?

梦想与她 提交于 2019-11-28 06:37:32

I use BeginRead, but continue blocking the thread using a WaitHandle:

byte[] readBuffer = new byte[32];
var asyncReader = stream.BeginRead(readBuffer, 0, readBuffer.Length, 
    null, null);

WaitHandle handle = asyncReader.AsyncWaitHandle;

// Give the reader 2seconds to respond with a value
bool completed = handle.WaitOne(2000, false);
if (completed)
{
    int bytesRead = stream.EndRead(asyncReader);

    StringBuilder message = new StringBuilder();
    message.Append(Encoding.ASCII.GetString(readBuffer, 0, bytesRead));
}

Basically it allows a timeout of the async reads using the WaitHandle and gives you a boolean value (completed) if the read was completed in the set time (2000 in this case).

Here's my full stream reading code copied and pasted from one of my Windows Mobile projects:

private static bool GetResponse(NetworkStream stream, out string response)
{
    byte[] readBuffer = new byte[32];
    var asyncReader = stream.BeginRead(readBuffer, 0, readBuffer.Length, null, null);
    WaitHandle handle = asyncReader.AsyncWaitHandle;

    // Give the reader 2seconds to respond with a value
    bool completed = handle.WaitOne(2000, false);
    if (completed)
    {
        int bytesRead = stream.EndRead(asyncReader);

        StringBuilder message = new StringBuilder();
        message.Append(Encoding.ASCII.GetString(readBuffer, 0, bytesRead));

        if (bytesRead == readBuffer.Length)
        {
            // There's possibly more than 32 bytes to read, so get the next 
            // section of the response
            string continuedResponse;
            if (GetResponse(stream, out continuedResponse))
            {
                message.Append(continuedResponse);
            }
        }

        response = message.ToString();
        return true;
    }
    else
    {
        int bytesRead = stream.EndRead(asyncReader);
        if (bytesRead == 0)
        {
            // 0 bytes were returned, so the read has finished
            response = string.Empty;
            return true;
        }
        else
        {
            throw new TimeoutException(
                "The device failed to read in an appropriate amount of time.");
        }
    }
}

Async I/O can be used to achieve the same amount of I/O in less threads.

As you note, right now your app has one thread per Stream. This is OK with small numbers of connections, but what if you need to support 10000 at once? With async I/O, this is no longer necessary because the read completion callback allows context to be passed identifying the relevant stream. Your reads no longer block, so you don't need one thread per Stream.

Whether you use sync or async I/O, there is a way to detect and handle stream closedown on the relevant API return codes. BeginRead should fail with IOException if the socket has already been closed. A closedown while your async read is pending will trigger a callback, and EndRead will then tell you the state of play.

When your application calls BeginRead, the system will wait until data is received or an error occurs, and then the system will use a separate thread to execute the specified callback method, and blocks on EndRead until the provided NetworkStream reads data or throws an exception.

Did you try server.ReceiveTimeout? You can set the time which Read() functon will wait for incomming data before returning zero. In your case, this property is probably set to infinite somewhere.

Bonshington

BeginRead is an async process which means your main thread will start execute Read in another process. So now we have 2 parallel processes. if u want to get the result, u have to call EndRead, which will gives the result.

some psudo

BeginRead()
//...do something in main object while result is fetching in another thread
var result = EndRead();

but if your main thread doesn't have anything else to do and u have to need the result, u should call Read.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!