使用NetworkStream.BeginRead()获取IOException

时间:2014-02-08 21:59:11

标签: c# ioexception networkstream beginread

运行此代码时:

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);
        }                
    }
}

我从BeginRead收到以下IO异常:

  

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

以下是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重置为空数组,但这也不起作用。

任何帮助都将不胜感激。

2 个答案:

答案 0 :(得分:2)

你正在运行一个没有任何限制的无限循环。您可以像CPU一样快地发出异步读取调用。这会产生无限量的未完成操作。

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

只需添加

if (myStream.DataAvailable)

您可以避免读取但仍然刻录一个CPU内核。这只是其中一种症状的缓解。而是修复根本原因。

看起来你根本不应该做异步IO因为你没有阻塞问题。你正在阻止一个线程并烧掉100%的核心。如果这是可以接受的,甚至不要打扰异步IO。

或者,使用await ReadAsync

答案 1 :(得分:0)

我找到了解决办法。

在尝试BeginRead之前,我会使用NetworkStream.DataAvailable或我的案例myStream.DataAvailable检查流是否有任何可用数据

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

if (myStream.DataAvailable){
    myStream.BeginRead(myBuffer, 0, BUFFER_SIZE, new AsyncCallback(UpdateChatBoxAsync), myStream);
}