Stream EndRead何时阻止回调

时间:2013-04-29 14:11:40

标签: c# sockets asynchronous stream

我对使用Async模式进行流读取和写入相对较新,并且想知道这个问题的答案是否如此明显,它是不是明确地写在任何地方:

当调用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
    }

3 个答案:

答案 0 :(得分:1)

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

  • 您可以在回调函数中使用EndRead。此时不会阻止任何事情。
  • 您也可以在没有回叫功能的情况下使用EndRead:

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

应始终调用EndRead来报告发生的一些错误。如果发生错误,EndRead将抛出异常。

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

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