在MFC 中创建一个子线程, pThread=AfxBeginThread(ThreadRdNetServer,(LPVOID)this);当程序退出时,子线程被强制关闭,子程序的资源没有回收,会造成内存泄漏:
Detected memory leaks!
Dumping objects ->
f:\rtm\vctools\vc7libs\ship\atlmfc\src\mfc\thrdcore.cpp(306) : {83} client block at 0x01C98C00, subtype c0, 68 bytes long.
a CWinThread object at $01C98C00, 68 bytes long
解决这个问题,可以定义一个BOOL型的变量BOOL g_bThread = TRUE,作为子线程的循环条件,在主线程的退出函数里,用WaitForSingleObject获取线程状态,等待线程后,再退出程序:
void CXXXDlg::OnDestroy() { CDialog::OnDestroy(); g_bThread = FALSE; WaitForSingleObject(pThread->m_hThread,INFINITE); }
若子线程是TCP 的服务器:
SOCKET sockSrv; SOCKET sockConn; UINT CTcpServerDlg:: ThreadNetServer(LPVOID pParam) { ...... //创建用于监听的套接字 sockSrv = socket(AF_INET, SOCK_STREAM, 0); ...... while(g_bThread) { //等待客户端请求到来 sockConn = accept(sockSrv, (SOCKADDR *)&addrClient, &len); if (sockConn==INVALID_SOCKET) { continue; } char recvBuf[100]={'\0'}; recv(sockConn, recvBuf, 100, 0); //接受数据 ...... } closesocket(sockSrv);//关闭监听套接字 WSACleanup(); // 卸载winsock library }
线程会阻塞在函数accept 、 recv 处;即使循环条件g_bThread = FALSE, 因为线程阻塞也无法跳出循环,这个时候若是关闭对话框,会阻塞在函数 WaitForSingleObject无法退出
解决方法:要使程序从accept 中返回,可以在主程序中关闭监听套接字sockSrv;这样accept 返回INVALID_SOCKET,执行continue,此时条件不成立从而跳出循环,结束子线程;
void CTcpServerDlg::OnDestroy() { CDialog::OnDestroy(); // TODO: Add your message handler code here //结束子线程 closesocket(sockSrv); g_bThread = FALSE; WaitForSingleObject(pThread->m_hThread,INFINITE); }
如此就可以安全的退出阻塞的子线程。