2

我对使用异步模式进行流读写比较陌生,想知道这个问题的答案是否如此明显以至于没有明确地写在任何地方:

调用 a 时NetworkStream.BeginRead,我传递了一个回调参数,根据 MSDN,该参数在“BeginRead 完成时”执行。它还说“你的回调方法应该调用 EndRead 方法”。

然后根据文档NetworkStream.EndRead,“方法完成在 BeginRead 方法中启动的异步读取操作”。它还提到这种方法“在数据可用之前一直阻塞”。

我知道 EndRead 方法对于确定接收到的字节数也很有用。

我的问题是:

如果在 BeginRead 回调中调用 EndRead 方法,它真的会阻塞吗?调用回调时读取操作不是已经完成了吗?

示例代码

    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
    }
4

3 回答 3

2

回调触发时,读取操作始终完成。完成是首先触发回调的原因。所以 EndRead() 在回调方法中使用时永远不会阻塞。

请注意,“完成”也可能意味着“失败”,EndRead() 将抛出异常。一个非常常见的异常是 ObjectDisposedException,在异步读取正在进行时关闭套接字时抛出。典型的当你退出你的程序时,一定要抓住它。

于 2013-04-29T14:38:55.313 回答
1

您可以在两种情况下使用 EndRead:

  • 您可以在回调函数中使用 EndRead。在这一点上,什么都不会被阻止。
  • 您也可以在没有回调函数的情况下使用 EndRead:

    myStream.BeginRead(...);
    // 同时做很多工作。
    // 当我的工作完成后,等待流完成它的工作。
    myStream.EndRead(...);

应始终调用 EndRead 以报告发生了一些错误。如果发生错误,EndRead则会抛出异常。

于 2013-04-29T14:18:02.560 回答
0

不,因为该方法正在异步调用委托中EndRead被调用(并阻塞) 。所以是的,方法是阻塞的,但不是在调用的执行线程上。EndReadBeginRead

于 2013-04-29T14:16:59.037 回答