运行此代码时:
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重置为空数组,但这也不起作用。
任何帮助都将不胜感激。
答案 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);
}