我有一个使用.NET套接字的简单C#Async Client,它等待来自用于自动执行命令的本地Java服务器的定时消息 . 消息以异步方式进入,并写入环形缓冲区 . 此实现似乎在Windows Vista / 7/8和OSX上正常工作,但在从本地Java服务器接收消息时会随机抛出此异常:
未处理的异常:System.InvalidOperationException:只能为每个异步操作调用一次EndReceive . 在System.Net.Sockets.Socket.Socket.EndReceive(IAsyncResult asyncResult,SocketError&errorCode)的System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult)处于SocketTest.Controller.RecvAsyncCallback(IAsyncResult ar)的System.Net.LazyAsyncResult.Complete( IntPtr userToken)...
我在网上看到了这个错误,但没有发现任何真正有用的东西 . 这是它似乎破坏的代码:
/// <summary>
/// Callback to receive socket data
/// </summary>
/// <param name="ar">AsyncResult to pass to End</param>
private void RecvAsyncCallback(IAsyncResult ar)
{
// The exception will randomly happen on this call
int bytes = _socket.EndReceive(_recvAsyncResult);
// check for connection closed
if (bytes == 0)
{
return;
}
_ringBuffer.Write(_buffer, 0, bytes);
// Checks buffer
CheckBuffer();
_recvAsyncResult = _sock.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, RecvAsyncCallback, null);
}
除了在接收消息的过程中,该错误不会发生在任何特定时刻 . 消息本身可以是任何长度,并且异常可以立即发生,有时甚至可以达到完美通信的一分钟 .
我对套接字和网络通信很新,我觉得我可能会遗漏一些东西 . 我已经在至少8台不同的计算机上进行了测试,并且与引发此异常的计算机的唯一相似之处在于它们的操作系统是Windows XP 32位 .
1 回答
你会想要关注the convention shown here . 您正在传递
IAsyncResult
到Socket.BeginReceive
,它代表上下文中的不同点或完全不同的上下文 .确保在回调中使用的是在调用
EndReceive
时传入的参数 .Windows XP中可能有一个错误修复程序,具体取决于您的服务包以及您安装的其他内容,它会捕获上下文共享方案,或者可能是因为它引入了一个无法正确管理上下文的错误 . 没有广泛的测试,很难判断它是否是一个环境问题 .