问个VC的问题,多线程情况下,主线程在onclose()函数退出时,需要确认各个子线程完成了某件事情,于是我用一个while+sleep的代码来查询各个子线程对应的一组全局变量,看是否已经被子线程置1,全部置1主线程才返回,子线程也是while+sleep结构的,结果发现主线程在Sleep(50)处循环,子线程根本跑不到if处,导致软件退不出来。源码如下,请大侠指点:BOOL bExitThread[20];
HANDLE devHandle[20];
void CABCDlg::OnClose()
{
for (int i=0;i<20;i++)
{
bExitThread[i] = TRUE;
}
for(int i=0;i<20;i++)
{
while(devHandle[i] != NULL)
Sleep(50); }
CDialog::OnClose();
}UINT CAXToolDlg::TesterThreadFunc(LPVOID lparam)
{
while(1)
{
myfunc(devHandle);
Sleep(500);
if(bExitThread[lparam] == TRUE) //主线程发出了退出线程命令
{
::CloseHandle(devHandle[lparam]);
devHandle[lparam] = NULL;
return FALSE;
}
}
}子线程主线程
HANDLE devHandle[20];
void CABCDlg::OnClose()
{
for (int i=0;i<20;i++)
{
bExitThread[i] = TRUE;
}
for(int i=0;i<20;i++)
{
while(devHandle[i] != NULL)
Sleep(50); }
CDialog::OnClose();
}UINT CAXToolDlg::TesterThreadFunc(LPVOID lparam)
{
while(1)
{
myfunc(devHandle);
Sleep(500);
if(bExitThread[lparam] == TRUE) //主线程发出了退出线程命令
{
::CloseHandle(devHandle[lparam]);
devHandle[lparam] = NULL;
return FALSE;
}
}
}子线程主线程
{
while(devHandle[i] != NULL)
Sleep(50);
}
上面的语句就是死循环的,我猜测你的意思应该改为:
while(1)
{
int i=0;
for(i=0;i<20;i++)
{
if(devHandle[i] != NULL)
break;
}
if(i>=20)
break;
else
Sleep(50);
}
}
//程序退出保证所有子线程结束
static HANDLE s_ListenHandle;
//引用计数,默认是0
static int s_ListenCount = 0;
static CRITICAL_SECTION s_csListen;void ResetUserHandle()
{
EnterCriticalSection(&s_csListen);
if(s_ListenCount == 0)
{
ResetEvent(s_ListenHandle);
}
++s_ListenCount; //引用计数加1
LeaveCriticalSection(&s_csListen);
}void SetUserHandle()
{
EnterCriticalSection(&s_csListen);
--s_ListenCount;//引用计数减1
if (s_ListenCount == 0)
{
SetEvent(s_ListenHandle);
}
LeaveCriticalSection(&s_csListen);
}//线程函数的开始处调用ResetUserHandle(), 线程函数退出的地方调用SetUserHandle()//onclose里面这样调用:
DWORD ret = WaitForSingleObject(s_ListenHandle, 20000);//等待所有的子线程退出
if (ret == WAIT_TIMEOUT)
{
CDebug::Log("等待了20秒, 还有子线程没有退出");
}
else if (ret == WAIT_OBJECT_0)
{
CDebug::Log("所有子线程都退出了");
}
刚好我之前做的一个项目里面就有这个问题, 使用事件+引用计数来处理
试下这样
1.主线程设置退出标志
2.主线程等待子线程退出WaitForMultiObjects
3.大家都退出了
看来问题是出在子线程上面,因为发现主线程通过全局变量bExitThread[i] = TRUE;告诉子需要退出时,子线程并没有退出;
new 一个 devHandle 必须马上为相应的创建个线程(LPVOID lparam)线程参数要正确。