Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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# 第二次调用NetworkStream beginhead()大规模资源争用_C#_Multithreading_Asynchronous_Tcpclient_Networkstream - Fatal编程技术网

C# 第二次调用NetworkStream beginhead()大规模资源争用

C# 第二次调用NetworkStream beginhead()大规模资源争用,c#,multithreading,asynchronous,tcpclient,networkstream,C#,Multithreading,Asynchronous,Tcpclient,Networkstream,我正在用TcpClient和NetworkStream对象编写服务器/客户端项目。我希望许多客户端连接到服务器,这些客户端存储在自定义网络节点对象的列表中,每个对象都有一个TcpClient和一个NetworkStream,用于与相应的客户端通信 服务器需要能够保持与客户端的连接,并在收到消息后立即(快速)等待和操作消息。对于这个应用程序来说,同步轮询是非常不可取的,我也不希望以这种方式编写它 目前,服务器正在异步接受客户机,并将其添加到列表中,工作非常顺利。我用一个控制台应用程序测试了这一点,

我正在用
TcpClient
NetworkStream
对象编写服务器/客户端项目。我希望许多客户端连接到服务器,这些客户端存储在自定义
网络节点
对象的
列表中,每个对象都有一个
TcpClient
和一个
NetworkStream
,用于与相应的客户端通信

服务器需要能够保持与客户端的连接,并在收到消息后立即(快速)等待和操作消息。对于这个应用程序来说,同步轮询是非常不可取的,我也不希望以这种方式编写它

目前,服务器正在异步接受客户机,并将其添加到
列表中
,工作非常顺利。我用一个控制台应用程序测试了这一点,该应用程序生成多达100个客户端,并在很短的时间内(<1秒)通过环回地址连接到服务器

将客户端添加到
列表中时
对象使用
GetStream()
方法返回客户端的
NetworkStream
对象。我正在尝试使用
NetworkStream.BeginRead()
方法实现来自每个TCP客户端的异步数据接收。对该方法的第一次调用如下所示:

this.Stream.BeginRead(readBuffer, readBufferOffset, readBuffer.Length - readBufferOffset, 
    new AsyncCallback(nodeStreamReadCallback), this.Stream);
由于console测试应用程序在连接到服务器后立即发送一些数据,因此对象的
readCallback(IAsyncResult)
方法几乎立即被调用:

private void readCallback(IAsyncResult ar)
{
    NetworkStream _stream = (NetworkStream)ar.AsyncState;

    int _bytesRead = 0;

    _bytesRead = _stream.EndRead(ar);

    this.Stream.Write(readBuffer, readBufferOffset, _bytesRead);

    //increase buffer offset value
    readBufferOffset += _bytesRead;

    //TODO process the received data
    ...

    //wait for the next chunk of data
    this.Stream.BeginRead(readBuffer, readBufferOffset, readBuffer.Length - readBufferOffset, 
    new AsyncCallback(readCallback), this.Stream);
}
我正在对Stream.BeginRead()执行第二个调用,目的是等待下一个数据块到达或可用,无论将来何时

当我注释掉对
Stream.BeginRead()
的第二个调用时,所有操作都非常顺利。所有数据都被接收并发送回每个客户机,没有延迟,并且线程使用量极低(在这个过程中,平均增加2到3个线程)

但是-即使只有一个单客户端连接,如果我尝试在
readCallback()
方法(如上)内对
Stream.BeginRead()
进行第二次调用,我也会遇到大量的争用问题。对于单个客户机,第二次调用后的CPU使用率从~0%跳到30%到60%之间,线程数可以从11跳到35

所以这是一个线程或递归问题,我觉得我应该等待一些东西,但我不能完全理解这里发生的事情。这与我使用的
TcpListener.BeginAcceptTcpClient()
的模式相同,因此我认为它必须以不同的方式运行


我感谢您可能提供的所有建议,并提前感谢您的帮助

检查您的
\u bytesRead
是否为0,因为这意味着您的流在远程端被关闭。在这样的流上再次调用
BeginRead
会直接导致调用回调时读取字节的计数一次又一次为0。

您是否检查了
\u bytesRead
是否为0?因为这意味着您的流在远程端被关闭。在这样的流上再次调用
BeginRead
将直接导致反复调用读取字节数为0的回调。您在哪里重置
readBufferOffset
?@abto您是对的!在我的控制台测试应用程序中,我使用(NetworkStream=client.GetStream(){}通过
发送数据
block。当使用块完成发送数据时,流不再可用,并在
\u bytesRead
参数中返回0。检查此项可防止无限循环。谢谢!这确实是答案,请您将其移动到答案中,以便我可以将其标记为正确。您是对的!在我的控制台测试应用程序中操作I通过
使用(NetworkStream=client.GetStream(){}
块发送数据。当使用块完成发送数据时,流不再可用,并在
\u bytesRead
参数中返回0。检查此操作可防止循环。