zoukankan      html  css  js  c++  java
  • 安全退出阻塞的子线程

    在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);
    }

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

  • 相关阅读:
    MySQL之字符集
    PHP7.0-PHP7.3新特性与变更
    MySQL之开发规范
    php框架之thinkphp
    MySQL之日期时间类型
    php扩展之Yar
    XAMPP支持多PHP版本
    MySQL之执行流程
    RabbitMQ之php-amqplib使用
    (转)YAML最最基础语法
  • 原文地址:https://www.cnblogs.com/small-lazybee/p/9953181.html
Copyright © 2011-2022 走看看