Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 流EndRead何时阻止回调_C#_Sockets_Asynchronous_Stream - Fatal编程技术网

C# 流EndRead何时阻止回调

C# 流EndRead何时阻止回调,c#,sockets,asynchronous,stream,C#,Sockets,Asynchronous,Stream,我对使用异步模式进行流读写比较陌生,我想知道这个问题的答案是否如此明显以至于没有明确地写在任何地方: 调用NetworkStream.BeginRead时,我传递了一个回调参数,根据MSDN,“当BeginRead完成时”执行该参数。它还说“您的回调方法应该调用EndRead方法。” 然后根据NetworkStream.EndRead的文档,“方法完成在BeginRead方法中启动的异步读取操作。”它还提到此方法“阻塞直到数据可用。” 我知道EndRead方法对于确定接收的字节数也很有用 我的问

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

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

否,因为正在异步调用的委托中调用(并阻塞)了
EndRead
方法。因此,是的,
EndRead
的方法是阻塞的,但不是在调用
BeginRead
的执行线程上。您可以在两种情况下使用EndRead:

  • 您可以在回拨函数中使用EndRead。在这一点上,任何东西都不会被阻止
  • 您也可以在不使用回调函数的情况下使用EndRead:

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

应始终调用EndRead以报告发生的某些错误。如果发生错误,
EndRead
将引发异常。

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


请注意,“completed”也可以表示“failed”,EndRead()将引发异常。一个非常常见的异常是ObjectDisposedException,它是在异步读取过程中关闭套接字时引发的。退出程序时,请务必捕获它。

请发布一些代码。该调用可能是一个“阻塞”调用,但实际是否会阻塞委托线程?调用EndRead块之前,EndRead块的结束条件是否已完成?但回调中是否需要EndRead?我见过一些从未使用过的例子,这些都是糟糕的例子。是的,在使用APM时,对BeginXXX的每次调用都应与对EndXXX的调用配对。就个人而言,随着NET4.5和C 5的<代码>异步/等待> /代码>的出现,我会考虑这些API被有效地贬低。@斯宾德:为什么那些坏例子?它认为这正好回答了他的问题。他的问题不是:“我能用另一种/更好的方式吗?”?他问EndRead什么时候会被阻塞。也许他没有使用.NET4.5。@MartinMulder:我在上面的评论中提到了OP提到的例子,其中在BeginXXX之后没有调用EndXXX。我的评论不是关于你的回答。抱歉搞混了。你的回答很好。@spender:接受道歉。现在给我一个很大的选票P