安全退出阻塞的子线程

在MFC 中创建一个子线程, pThread=AfxBeginThread(ThreadRdNetServer,(LPVOID)this);当程序退出时,子线程被强制关闭,子程序的资源没有回收,会造成内存泄漏:

Detected memory leaks!

Dumping objects ->

f: tmvctoolsvc7libsshipatlmfcsrcmfc hrdcore.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]={''};
		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);
}

如此就可以安全的退出阻塞的子线程。

原文地址:https://www.cnblogs.com/small-lazybee/p/9953181.html