首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VC/MFC >

关于线程退出的有关问题

2012-03-14 
关于线程退出的问题线程退出后死锁我先把相关代码帖出来,问题描述在后面void CMulThreadDialog::OnOK(){  

关于线程退出的问题
线程退出后死锁

我先把相关代码帖出来,问题描述在后面

void CMulThreadDialog::OnOK()
{
    ......
    m_pCmdThread = AfxBeginThread(CmdTdFunction, (LPVOID)this);
}

UINT __cdecl CMulThreadDialog::CmdTdFunction( LPVOID pParam )
{
CMulThreadDialog * pDlg = (CMulThreadDialog *)pParam;
pDlg->DoCommand();
PostMessage(WM_COMMAND, UM_ENDDIALOG, 0);
WriteLog(1000,1000,_T("the hthread: 0x%x run end"), pDlg->m_pCmdThread->m_hThread);
return 0;  
}

void CMulThreadDialog::OnEndDialog()
{
MSG msg;
while(PeekMessage(&msg, this->m_hWnd,UM_SETPROGPOS,UM_SETPROGPOS,PM_REMOVE ));
while(PeekMessage(&msg, this->m_hWnd,UM_ENABLEUI,UM_ENABLEUI,PM_REMOVE ));
WriteLog(1000, 1000, _T("In OnEndDialog ...\tm_pCmdThread: 0x%x, HTHREAD: 0x%x"), m_pCmdThread, m_pCmdThread->m_hThread);
if (m_pCmdThread && m_pCmdThread->m_hThread)
{
WaitForSingleObject(m_pCmdThread->m_hThread, INFINITE); //1,偶尔会死在此处
}
VisLogLine(1000, 1000, _T("OnEndDialog End"));
CDialog::OnOK();  //2,偶尔会死在此处                           
}

问题是为什么我的线程函数已经走到return 0;了,但是我在OnEndDialog函数里输出的log中可以看到m_pCmdThread->m_hThread这个值偶尔是个有效的线程句柄值. 当这个值是个无效值时也就是说线程return后被autodelete掉了,所以handle变为无效(0xcdcdcdcd)程序可以正常退出,但有时这个值仍有效, 这时return 0也走了,线程有时会死在1处,偶尔还会死在CDialog::OnOK();里,很迷惑..

[解决办法]

C/C++ code
void CMulThreadDialog::OnOK(){    ...    m_pCmdThread = AfxBeginThread(CmdTdFunction, (LPVOID)this);}UINT __cdecl CMulThreadDialog::CmdTdFunction( LPVOID pParam ){    CMulThreadDialog * pDlg = (CMulThreadDialog *)pParam;    pDlg->DoCommand();    PostMessage(WM_COMMAND, UM_ENDDIALOG, 0);    WriteLog(1000,1000,_T("the hthread: 0x%x run end"), pDlg->m_pCmdThread->m_hThread);    return 0;   }void CMulThreadDialog::OnEndDialog(){    MSG msg;    while(PeekMessage(&msg, this->m_hWnd,UM_SETPROGPOS,UM_SETPROGPOS,PM_REMOVE ));    while(PeekMessage(&msg, this->m_hWnd,UM_ENABLEUI,UM_ENABLEUI,PM_REMOVE ));    WriteLog(1000, 1000, _T("In OnEndDialog ...\tm_pCmdThread: 0x%x, HTHREAD: 0x%x"), m_pCmdThread, m_pCmdThread->m_hThread);    if (m_pCmdThread && m_pCmdThread->m_hThread)    {        WaitForSingleObject(m_pCmdThread->m_hThread, INFINITE);      //1,偶尔会死在此处    }    VisLogLine(1000, 1000, _T("OnEndDialog End"));    CDialog::OnOK();  //2,偶尔会死在此处                           }
[解决办法]
如果你要等待的话,其实等待线程句柄不是很好,可以自己定义一个Event等对象,然后一个线程中wait,当另一个线程退出时,SetEvent触发..
[解决办法]
如果要等待线程结束,就不要用AutoDelete的方式了。创建线程时指定CREATE_SUSPENDED标志,然后将m_bAutoDelete设置为FALSE,再ResumeThread。
[解决办法]
void CMulThreadDialog::OnOK() 

    ...... 
    m_pCmdThread = AfxBeginThread(CmdTdFunction, (LPVOID)this,THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED, NULL); 
m_pCmdThread->m_bAutoDelete = FALSE; // 保证线程退出码在外能被检查到。
 m_pCmdThread->ResumeThread();
 Sleep(100);


UINT __cdecl CMulThreadDialog::CmdTdFunction( LPVOID pParam ) 

CMulThreadDialog * pDlg = (CMulThreadDialog *)pParam; 
pDlg->DoCommand(); 
PostMessage(WM_COMMAND, UM_ENDDIALOG, 0); 
WriteLog(1000,1000,_T("the hthread: 0x%x run end"), pDlg->m_pCmdThread->m_hThread); 
return 0;


void CMulThreadDialog::OnEndDialog() 

MSG msg; 
while(PeekMessage(&msg, this->m_hWnd,UM_SETPROGPOS,UM_SETPROGPOS,PM_REMOVE )); 


while(PeekMessage(&msg, this->m_hWnd,UM_ENABLEUI,UM_ENABLEUI,PM_REMOVE )); 
WriteLog(1000, 1000, _T("In OnEndDialog ...\tm_pCmdThread: 0x%x, HTHREAD: 0x%x"), m_pCmdThread, m_pCmdThread->m_hThread); 
DWORD dwExitCode = STILL_ACTIVE;
 while(1)
 {
// 检索线程的退出代码前要求线程对象还没有退出
::GetExitCodeThread(m_pCmdThread->m_hThread, &dwExitCode);
if( dwExitCode != STILL_ACTIVE)
break;
 }
 // 手动删除线程对象
 delete m_pCmdThread;
 m_pCmdThread = NULL;
VisLogLine(1000, 1000, _T("OnEndDialog End")); 
CDialog::OnOK();                             
}
[解决办法]
对的m_bAutoDelete为TRUE的时候,线程return后,CWinThread *指向的指针内存对象被删除(这就是标准的野指针啊),所以不能并用。

至于是不是要用AutoDelete的模式要看你的应用,微软之所以把它的默认值设为TRUE,就是为了方便资源的自动释放。

热点排行