关于关闭管道的问题DisconnectNamedPipe
我使用了等待模式在线程中创建了管道,并等待客户端连接,连接成功后开始读取管道数据:
//首先:创建线程
m_hThread = CreateThread(NULL, 0, ThredFkt, this, 0, &m_nThreadID);
//线程函数
DWORD WINAPI CMyPipe::ThredFkt(LPVOID lpParameter)
{
CMyPipe* pThis = (CMyPipe*)lpParameter;
pThis->ReadPipe(); // 创建管道并监听客户端连接
return 0;
}
//创建管道,并等待客户端连接后读取管道数据
bool CMyPipe::ReadMyPipe()
{
m_hPipe = CreateNamedPipe(g_csPipeName, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES, 0, 0, 200, NULL);
if (ConnectNamedPipe(m_hPipe, NULL) == FALSE)
return false;
DWORD nReaded = 0;
char csPrefix[MAX_PATH];
char buffer[512];
while (ReadFile(m_hPipe, buffer, sizeof(buffer)-1, &nReaded, NULL))
{
...
//我在这里面有调用了CMyPipe的成员变量
...
}
SetEvent(m_hMsgEvent); // 发送消息,通知线程处理结束
return true;
}
//析构函数
CMyPipe::~CMyPipe(void)
{
ResetEvent(m_hMsgEvent); // 重置消息句柄
DisconnectNamedPipe(m_hPipe); // 关闭管道
WaitForSingleObject(m_hMsgEvent, INFINITE); // 等待线程退出 ???这边会被卡住
}
但是现在有个很奇怪的问题就是我在析构中调用了DisconnectNamedPipe()和WaitForSingleObject(),结果发现管道没有被关闭,没有执行SetEvent(m_hMsgEvent),导致了WaitForSingleObject()一直等待。
请教下是不是DisconnectNamedPipe()这个调用后不能马上调用WaitForSingleObject()等待。。。
由于我在while (ReadFile(m_hPipe, buffer, sizeof(buffer)-1, &nReaded, NULL))这个while里面有调用了CMyPipe的成员,如果我在析构中不等待线程先退出的话,会导致析构后如果while中调用了类的成员会崩掉。。。
请问下这种情况下应该怎么处理。。。我需要管道服务端主动断开与客户端的连接。。。
补充下:
我试了下分开调用DisconnectNamedPipe()和WaitForSingleObject(),不放在同一个函数里面,就可以通过,不会被卡住。
[解决办法]
你不应该在析构方法中调用WaitForSingleObject,而且你的这几段代码中也没有必要使用等待事件
[解决办法]
接着补充一下:为什么使用事件对象不可以呢,比如说服务端与客户端传输数据的时候,突然关闭了服务端,这样是不可能执行下面的那个SetEvent函数的,这样得不到通知,当然是会卡住的!
[解决办法]
WaitForSingleObject(m_hMsgEvent, 0)的等待时间为0,会马上返回不会阻塞,在msdn上查查WaitForSingleObject的用法和如何检查它的返回值吧。