3

运行此代码时:

private async void StartChat(Object obj)
{
    TcpClient me = (TcpClient)obj;
    UpdateChatBox("Attempting read from server.");
    myBuffer = new byte[BUFFER_SIZE];

    while (true)
    {
        var myStream = me.GetStream();
        myStream.BeginRead(myBuffer, 0, BUFFER_SIZE, new AsyncCallback(UpdateChatBoxAsync), myStream);

        if (messageToSend)
        {
            await myStream.WriteAsync(myMessage, 0, myMessage.Length);
        }                
    }
}

我收到以下 IO 异常BeginRead

无法从传输连接读取数据:无法对套接字执行操作,因为系统缺少足够的缓冲区空间或队列已满。

下面是 BeginRead 的回调方法:

private void UpdateChatBoxAsync(IAsyncResult result)
{
    var stream = result.AsyncState as NetworkStream;
    int bytesRead = stream.EndRead(result);

    if (bytesRead > 0)
    {
        String newMessage = NetworkUtils.GetString(myBuffer);
        UpdateChatBox(newMessage);
    }
}

有人可以说明引发此异常的原因吗?我每次都尝试在 while 循环开始时重新创建缓冲区,但是虽然这样做不会引发异常,但我不会从服务器接收消息。

我还尝试在 UpdateChatBoxAsync 结束时将 myBuffer 重置为空数组,这也不起作用。

任何帮助,将不胜感激。

4

2 回答 2

2

您正在运行一个无限循环,没有任何限制。您正在以 CPU 可以做到的速度发出异步读取调用。这会产生无限量的未完成操作。

您应该在最后一次读取完成时发出下一次读取(最常见的是通过回调完成)。

只需添加

if (myStream.DataAvailable)

您避免读取但仍会烧毁一个 CPU 内核。这只是缓解其中一种症状。而是修复根本原因。

看来您根本不应该进行异步 IO,因为您没有阻塞问题。您正在阻塞一个线程并燃烧 100% 的核心。如果这是可以接受的,甚至不要为异步 IO 烦恼。

或者,使用await ReadAsync.

于 2014-02-09T10:07:50.637 回答
0

我找到了我的解决方案。

在尝试之前,BeginRead我检查流是否有可用的数据,NetworkStream.DataAvailable或者在我的情况下myStream.DataAvailable

所以新的工作代码块看起来像

if (myStream.DataAvailable){
    myStream.BeginRead(myBuffer, 0, BUFFER_SIZE, new AsyncCallback(UpdateChatBoxAsync), myStream);
}
于 2014-02-09T06:52:52.347 回答