WaitForSingleObject的问题 本帖最后由 zxshift 于 2009-08-17 18:10:12 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 和双核没任何的关系。m_pCamThread在哪里被你搞丢了看不出来,看看有没有别的操作的地方 在Button2的WaitForSingleObject()执行之前,m_pCamThread一直正确,但到此句时,就会概率性的一直等待。摄像头线程以及其他地方都没有修改m_pCamThread的语句。 Button2的处理函数 void CFaceDlg::OnButton2() { // TODO: Add your control notification handler code here if(m_pCamThread) { CritSec.Lock(); ThreadFlag = 0; CritSec.Unlock(); ::WaitForSingleObject(m_pCamThread->m_hThread,INFINITE); m_pCamThread = NULL; } 你自己看....无语 原因不是这里,每次我都会新建一个摄像头线程,然后Button1和Button2才有效,因此执行Button2的处理函数时m_pCamThread是不会为空的。另外程序阻塞在::WaitForSingleObject(m_pCamThread->m_hThread,INFINITE); 此时,m_pCamThread = NULL;还未执行。 是不是因为楼主没有CloseHandle之后再去 m_pCamThread = NULL;的原因呢?楼主的这个做法线程计数器会累积的。 还有就是楼主的 m_pCamThread 一时锁一时不锁的,会不会在m_pCamThread赋值的地方产生了以外?如果你按完Button1马上按Button2可能会等死的。 谢谢各位大虾,问题已找到。用AfxBeginThread()创建的线程默认的m_bAutoDelete为TRUE,因此线程结束后自动析构CWinThread对象,从而导致m_hThread句柄无效。若WaitForSingleObject()抢在析构之前执行就能通过,因此产生概率性的死等。不过我仍然有点不明白的是为什么我点Button1时从未出现过死等呢?Button1应该和Button2是一样的呀?难道这也是概率性的事件,话说我都点了不下100遍了啊!! 综合以上大虾的意见,程序修改如下,大家看看还有没什么毛病!线程创建{ ............... CritSec.Lock(); if(!ThreadFlag) { ThreadFlag = 1; m_pCamThread = AfxBeginThread(CamThreadFunc,(LPVOID)this); m_pCamThread->m_bAutoDelete = false; } CritSec.Unlock(); ................... } 摄像头函数: UINT CFaceDlg::CamThreadFunc(LPVOID lpParam) { .... for(;;) { if(!ThreadFlag) return 0 ; .......... } return 0; } Button1的处理函数 void CFaceDlg::OnButton1() { // TODO: Add your control notification handler code here if(m_pCamThread) { CritSec.Lock(); ThreadFlag = 0; CritSec.Unlock(); ::WaitForSingleObject(m_pCamThread->m_hThread,INFINITE); ::CloseHandle(m_pCamThread->m_hThread); delete m_pCamThread; m_pCamThread = NULL; } ............ } Button2的处理函数一样 若WaitForSingleObject()抢在析构之前执行就能通过,因此产生概率性的死等。这个是什么意思?你还有析构?就算象你说的那样,最多会出错啊,不会等死的。除非线程还没结束不然程序总能退出的。 我的意思是用AfxBeginThread新建的线程,由于m_bAutoDelete为TRUE,因此线程结束时(即线程函数return时),系统会自动调用AfxBeginThread函数新建的线程对象的析构函数,关闭句柄,释放内存空间。若m_bAutoDelete为false,则不会。 我知道你的意思,也知道AfxBeginThread的AutoDel的用法,问题是就算发生你说问题::WaitForSingleObject(m_pCamThread->m_hThread,INFINITE); 这个地方会返回无效句柄的错误,不会等死的啊。 上面的程序还有一个错误的地方:::CloseHandle(m_pCamThread->m_hThread); 是多余的,直接delete m_pCamThread;就行了 ::CloseHandle(m_pCamThread->m_hThread); 不是多余的,线程的HANDLE是一个核心对象,你不关闭在线程多次创建再销毁后会出现非常多的内存泄露而且对于windows的程序来说不CloseHandle是不标准的。 之前在一论坛上看到说CwinThread对象的析构函数中会调用CloseHandle关闭线程的句柄.程序中有没有::CloseHandle(m_pCamThread->m_hThread); 我都试了,编译运行都能通过,但是若有::CloseHandle(m_pCamThread->m_hThread); 的话,在程序调试到delete m_pCamThread;时,会弹出一个提示消息框:First-Chance exception in Face.exe (NTDLL.DLL):0x.....:Invalid Handle. 因为没有必要delete m_pCamThreadAfxBeginThread不是New 你的意思是说 即使设置m_bAutoDelete = false,但由于用的AfxBeginThread,所以不需要delete吗? 刚看了下AfxBeginThread的实现。CWinThread* AFXAPI AfxBeginThread(AFX_THREADPROC pfnThreadProc, LPVOID pParam, int nPriority, UINT nStackSize, DWORD dwCreateFlags, LPSECURITY_ATTRIBUTES lpSecurityAttrs){ ................. CWinThread* pThread = DEBUG_NEW CWinThread(pfnThreadProc, pParam); ......... return pThread;}用DEBUG_NEW申请的内存,因此我觉得若m_bAutoDelete = false,就必须用户自己delete。 呵呵,不好意思,那个是我的错,因为我一直都用API来写,以为AfxBeginThread是CreateThread的封装,因此就理解成CreateThread的用法了。我刚刚也看了一下MSDN,如果楼主在::CloseHandle(m_pCamThread->m_hThread); 后出错的话证明CWinThread在析构的时候的确会自动CloseHandle,受教了。 消息响应优先级问题 ShowWindow(SW_HIDE)后状态栏图标没了 帮忙翻译句话 vc CListCtrl 锁定行头 获得其他程序中数据问题 请教下大家一个问题。 华为四面通过,兴奋+担忧 请教,此界面怎么做? 邀请网络高手解决 想要做个聊天软件 无从下手 关于蓝牙文件传输 ClistCtrl有一个成员函数GetEditControl(),应该跟列表编辑有关,但是不知道怎么用.大家帮帮忙.
m_pCamThread在哪里被你搞丢了看不出来,看看有没有别的操作的地方
void CFaceDlg::OnButton2()
{
// TODO: Add your control notification handler code here
if(m_pCamThread)
{
CritSec.Lock();
ThreadFlag = 0;
CritSec.Unlock();
::WaitForSingleObject(m_pCamThread->m_hThread,INFINITE);
m_pCamThread = NULL; } 你自己看....无语
::WaitForSingleObject(m_pCamThread->m_hThread,INFINITE);
此时,m_pCamThread = NULL;还未执行。
用AfxBeginThread()创建的线程默认的m_bAutoDelete为TRUE,因此线程结束后自动析构CWinThread对象,从而导致m_hThread句柄无效。若WaitForSingleObject()抢在析构之前执行就能通过,因此产生概率性的死等。不过我仍然有点不明白的是为什么我点Button1时从未出现过死等呢?Button1应该和Button2是一样的呀?难道这也是概率性的事件,话说我都点了不下100遍了啊!!
{
...............
CritSec.Lock();
if(!ThreadFlag)
{
ThreadFlag = 1;
m_pCamThread = AfxBeginThread(CamThreadFunc,(LPVOID)this);
m_pCamThread->m_bAutoDelete = false;
}
CritSec.Unlock();
...................
} 摄像头函数:
UINT CFaceDlg::CamThreadFunc(LPVOID lpParam)
{
....
for(;;)
{
if(!ThreadFlag) return 0 ;
..........
}
return 0;
} Button1的处理函数
void CFaceDlg::OnButton1()
{
// TODO: Add your control notification handler code here
if(m_pCamThread)
{
CritSec.Lock();
ThreadFlag = 0;
CritSec.Unlock();
::WaitForSingleObject(m_pCamThread->m_hThread,INFINITE);
::CloseHandle(m_pCamThread->m_hThread);
delete m_pCamThread;
m_pCamThread = NULL;
}
............
} Button2的处理函数一样
我的意思是用AfxBeginThread新建的线程,由于m_bAutoDelete为TRUE,因此线程结束时(即线程函数return时),系统会自动调用AfxBeginThread函数新建的线程对象的析构函数,关闭句柄,释放内存空间。若m_bAutoDelete为false,则不会。
::CloseHandle(m_pCamThread->m_hThread); 是多余的,直接delete m_pCamThread;就行了
但是若有::CloseHandle(m_pCamThread->m_hThread); 的话,在程序调试到delete m_pCamThread;时,会弹出一个提示消息框:
First-Chance exception in Face.exe (NTDLL.DLL):0x.....:Invalid Handle.
你的意思是说 即使设置m_bAutoDelete = false,但由于用的AfxBeginThread,所以不需要delete吗?
CWinThread* AFXAPI AfxBeginThread(AFX_THREADPROC pfnThreadProc, LPVOID pParam,
int nPriority, UINT nStackSize, DWORD dwCreateFlags,
LPSECURITY_ATTRIBUTES lpSecurityAttrs)
{
.................
CWinThread* pThread = DEBUG_NEW CWinThread(pfnThreadProc, pParam);
.........
return pThread;
}用DEBUG_NEW申请的内存,因此我觉得若m_bAutoDelete = false,就必须用户自己delete。