BOOL Interface::Listen()
{
m_bLoop = TRUE; DWORD dwThreadID;
m_hListenerThread = ::CreateThread(
(LPSECURITY_ATTRIBUTES)NULL,
0,
(LPTHREAD_START_ROUTINE)_threadProc,
this,
0,
&dwThreadID
);
if (m_hListenerThread == INVALID_HANDLE_VALUE) {
m_bLoop = FALSE;
goto _err;
}
return TRUE;_err: if (m_hDevice)  {
CloseHandle(m_hDevice);
m_hDevice = NULL;
}
return FALSE;
}/*!
\brief Abort Listenning for Interface. \param lpszName [in] Device Name. \retval TRUE Success.
\retval FALSE Failure.
*/
void Interface::Abort()
{
m_bLoop = FALSE;
FUNC_START_LOG("Abort");
if (m_hListenerThread) 
{
::WaitForSingleObject(m_hListenerThread, 10000);
FUNC_END_LOG("Abort"); ::CloseHandle(m_hListenerThread);
m_hListenerThread = NULL;
}
}DWORD WINAPI Interface::_threadProc(void *pObject)
{
Interface *pThis = (Interface*)pObject;
return pThis->_listenerLoop();
}DWORD Interface::_listenerLoop()
{
BYTE report[256];
REPORT decrep;  FUNC_START_LOG("listenerLoop");
while (m_bLoop) 
{
DWORD dwLen = _readReport(report, sizeof(report), 30000);
if (dwLen > 0) {
memset(&decrep, 0, sizeof(decrep));
if (_decodeReport(&decrep, report, dwLen)) {
if (m_pSignPad) m_pSignPad->onReceive(&decrep);
}
}
}
FUNC_END_LOG("listenerLoop");
return 0;
}1.abort函数中,m_bLoop = FALSE;这个变量改变,并没有使_listenerLoop()函数while循环立即结束,也就导致了::WaitForSingleObject(m_hListenerThread, 10000);等待失败。直接closehandle其句柄,可能有什么异常呢?1。我的问题是怎么在Abort中合理地终止线程,或者_listenerLoop()函数怎么更加合理些?该程序还有其他不合理的地方吗?2. 在c++运行库中直接调用createthead函数会导致内存泄露,是这样子的吗?

解决方案 »

  1.   

    1.while循环中调用Abort函数 如果符合条件则break
    2.木有这么一说吧
      

  2.   

    ::WaitForSingleObject(m_hListenerThread, 10000);
    DWORD dwLen = _readReport(report, sizeof(report), 30000);如果 每次loop执行时间大于10000,导致 wait 失败或是超时多线程对m_bLoop处理,最好加上同步机制
      

  3.   

    你这样的设计挺好的。m_bLoop 通过这个变量来控制线程自动退出。不需要closehandle。应该是不会有泄漏发生的。
      

  4.   


    经过日志发现,Abort中的m_bLoop变量改变并没有使线程自动退出。。
      

  5.   

    m_bLoop 修改的地方的日记打出来看看,不可能false while循环还继续的道理。
      

  6.   

    11:04:29 4453968 start listenerLoop
    11:04:31 4456500 start Disconnect()
    11:04:31 4456500 start Abort
    11:04:41 4466500 end Abort
    11:04:41 4466500 end listenerLoop
    11:04:41 4466515 start Abort
    11:04:41 4466515 start ~Interface()
    11:04:41 4466515 start Abort
    11:04:41 4466515 start ~Interface()
    11:04:41 4466515 end Disconnect()
      

  7.   

    11:04:31 4456500 start Abort
    11:04:41 4466500 end Abort这一步等待了将近 10s
      

  8.   

    你等的时间有点短
    既然确定循环能退出WaitForSingleObject的第二个参数应该设为INFINITE
    然后
    CreateThread是windows的API不是CRT的函数
    CRT中启动线程的函数时_beginthread
    用这个操作线程确实比CreateThread安全
    主要区别在于异常处理方面
    windows核心编程有关于这方面的介绍
    有兴趣你可以看看
      

  9.   


    +1
    正确的写法都是必须等待线程自己退出后再closehandle的, 不应该采用10S.
      

  10.   

    HANDLE  m_ExitEvent;m_ExitEvent = CreateEvent( NULL, true, false, NULL );_beginthreadex( NULL, 0, __COMMThread, this, 0, NULL );//线程体
    unsigned __stdcall __COMMThread( void* pVoid )
    { CSuperAlarmDeviceUnit* pServer = ( CSuperAlarmDeviceUnit* ) pVoid;

    pServer->Run(); SetEvent( pServer->m_ExitEvent ); _endthreadex( 0 ); return 0;}//等待退出
    WaitForSingleObject( m_ExitEvent, INFINITE );
    线程安全退出自己设个信号量比较简单些,creaatethread会导致内存泄露,但是楼主这样操作是不会的。推荐还是用begin吧。如果你线程体执行时间较长,线程确实会等待比较久。如果实在没办法,考虑在外部杀死线程吧。
      

  11.   

    lz设计abort的目的是什么?是为了强制终止线程吗?一般不推荐lz这种设计方法哦。
    如果是我的话会这样设计。void Interface::Abort()
    {
        m_bLoop = FALSE;
        FUNC_START_LOG("Abort");    
        if (m_hListenerThread) 
        {
            ::WaitForSingleObject(m_hListenerThread, INFINITE);   //一直等待线程函数返回
            FUNC_END_LOG("Abort");        ::CloseHandle(m_hListenerThread);
            m_hListenerThread = NULL;
        }
    }DWORD Interface::_listenerLoop()
    {
        BYTE report[256];
        REPORT    decrep;     FUNC_START_LOG("listenerLoop");    
        while (m_bLoop) 
        {
            DWORD dwLen = _readReport(report, sizeof(report), 30000);
            if (dwLen > 0) {
                memset(&decrep, 0, sizeof(decrep));
                if (_decodeReport(&decrep, report, dwLen)) {
                    if (m_pSignPad) m_pSignPad->onReceive(&decrep);
                }
            }
            else
            {
              break;   //这里跳出循环,结束线程函数
            }
        }
        FUNC_END_LOG("listenerLoop");    
        return 0;
    }