我正在尝试使用从kernel32.dll
和ws2_32.dll
导入的Win32API使用C#编写IOCP服务器。
问题出现在工作线程中。如果我经常向服务器发出请求,它会在十秒内死掉。 (打破循环!)详细情况是,在GetQueuedCompletionStatus()
函数返回false
后,返回的整数指针lpOverlapped
为NULL
,GetLastWin32Error()
返回代码735,是ERROR_ABANDONED_WAIT_0
。
错误在msdn中描述如下:
如果对
GetQueuedCompletionStatus
的调用失败,因为与调用相关的完成端口句柄在调用未完成时关闭,则函数返回FALSE
, * lpOverlapped 将为{ {1}},NULL
将返回GetLastError
。
但是当我调试程序时,ERROR_ABANDONED_WAIT_0
变量是有效的,并且看起来似乎没有关闭完成端口。请看一下代码。
completionPort
我认为完成端口是O.K.所以我首先将public int WorkerThread()
{
...
while (true) {
// Wait until all socket I/O completes.
bool ret = GetQueuedCompletionStatus(
completionPort: completionPort,
lpNumberOfBytesTransferred: out bytesTransferred,
lpCompletionKey: out intPtrPerHandleData,
lpOverlapped: out intPtrOverlapped,
dwMilliseconds: uint.MaxValue);
// WHAT IS WRONG!?!??!
if (intPtrOverlapped == IntPtr.Zero)
{
Logger.ErrorLog();
break;
}
// Recover PerIoData and PerHandleData from IntPtr
...
// Disconnected from client.
if (ret == false && bytesTransferred == 0) {
socketRefCount[perHandleData.Socket]--;
if (socketRefCount[perHandleData.Socket] == 0)
{
socketRefCount.Remove(perHandleData.Socket);
perHandleData.Socket.Close();
}
gchPerHandleData.Free();
gchPerIoData.Free();
}
}
}
子句更改为break
。然后它首先产生735错误(continue
),然后无限制地产生错误代码6(ERROR_ABANDONED_WAIT_0
)。以下是简化的日志。
WSA_INVALID_HANDLE
所以完成端口有问题,对吗?你能解释一下我遇到的问题是什么以及可能导致这个问题的原因吗? (我每秒只发出大约十到二十个50字节的消息。我认为它很少,但服务器甚至一分钟都无法负担!)我每次都需要重建I / O完成端口和工作线程发生错误? (即重置服务器?)
---更新! 添加了完整版的工作线程代码:http://ideone.com/J0flmC