NetworkStream.Read()和NetworkStream.BeginRead()之间的区别?区别、NetworkStream、Read、BeginRead

2023-09-02 01:56:46 作者:哥不帅但很坏

我需要从的NetworkStream 来阅读这将随机发送数据和数据包的大小也不断变化。我实现了多线程应用程序,每个线程将有自己的流从阅读。如果在流中没有数据时,应用程序应该保持等待数据成为到达。但是,如果服务器完成发送数据和终止会话,那么它应该退出了。

I need to read from NetworkStream which would send data randomly and the size of data packets also keep varying. I am implementing a multi-threaded application where each thread would have its own Stream to read from. If there is no data on the stream, the application should keep waiting for the Data to arrive. However, If the Server is done sending data and has terminated the session, then it should exit out.

起初,我已经使用了方法来获取从流中的数据,但它用来阻塞线程,并一直在等待出现在流,直到数据。

Initially I had utilised the Read method to obtain the data from the stream, but it used to block the thread and kept waiting untill data appeared on the Stream.

在MSDN上的文档显示,

The documentation on MSDN suggests,

如果没有数据可用于阅读,   Read方法返回0。如果   远程主机关闭连接,   和所有可用的数据已经   收到,Read方法完成   立即返回零字节。

If no data is available for reading, the Read method returns 0. If the remote host shuts down the connection, and all available data has been received, the Read method completes immediately and return zero bytes.

不过,在我的情况,我从来没有得到方法返回0,正常退出。它只是无限期地等待。

But in my case, I have never got the Read method to return 0 and exit gracefully. It just waits indefinately.

在我进一步的调查,我碰到的BeginRead 这手表流和异步,尽快临危数据调用的回调方法。我试图寻找使用这种方法,以及各种实现,但是,我无法时候会使用,以确定的BeginRead 是benificial而不是阅读

In my further investigation, I came across BeginRead which watches the Stream and invokes a callback method Asynchronously, as soon as it recieves the data. I have tried to look for various implementations using this approach as well, however, I was unable to identify when would using BeginRead be benificial as opposed to Read.

当我看着它,的BeginRead 有具有异步调用,这将不会阻止当前线程刚刚优势。但是,在我的应用程序,我已经有一个单独的线程读取和流处理数据,从而使wouldnt太大的差别我。

As I look at it, BeginRead has just the advantage of having the async call, which would not block the current thread. But in my application, I already have a seperate thread to Read and process the data from stream, so that wouldnt make much difference for me.

任何人都可以请帮助我了解 等待和退出机制 的BeginRead 和它是如何的不同 从

Can anyone please help me understand the Wait and Exit mechanism for BeginRead and how is it different from Read?

什么是执行所需functionlity最好的方法是什么?

What would be the best way to implement the desired functionlity?

推荐答案

我用的BeginRead ,而是继续阻止使用线程的WaitHandle

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));
}

基本上,它允许异步的超时读取使用的WaitHandle ,并给你一个布尔值(完成)如果读取是在设定的时间内完成( 2000年在这种情况下,)。

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).

下面是我的全码流的阅读code复制,并从我的Windows Mobile项目之一粘贴:

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.");
        }
    }
}