主线程等待子线程的问题

土掉渣 2013-05-03 07:21:09
问个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;
}
}
}
...全文
215 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
土掉渣 2013-05-14
  • 打赏
  • 举报
回复
多谢各位的关注,问题我自己找到了:OnClose是一个消息函数,而我在myfunc(devHandle)函数中给主窗口用SendMessage()发送的一些消息,这样就冲突了,后来换成PostMessage替换后就解决。
wumn29 2013-05-06
  • 打赏
  • 举报
回复

//程序退出保证所有子线程结束
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("所有子线程都退出了");
	}
刚好我之前做的一个项目里面就有这个问题, 使用事件+引用计数来处理
  • 打赏
  • 举报
回复
但看这2段代码没发现什么问题啊。检查下其它地方呢? 比如初始化 devHandle[20] 保证都为NULL, new 一个 devHandle 必须马上为相应的创建个线程(LPVOID lparam)线程参数要正确。
土掉渣 2013-05-06
  • 打赏
  • 举报
回复
主线程一直在Sleep处,子线程无论在哪里打断点都跑不到,WatitForSingleObject这个我也试过了,跟用全局变量是一样的效果。
土掉渣 2013-05-06
  • 打赏
  • 举报
回复
我的意思是OnClose()里面,20个子线程必须全部将devHandle设置为NULL之后才能才能退出for,这样才能安全退出程序,否则任意一个子线程没有安全关闭devHandle,都有可能导致硬件(USB设备)跑死。因此,我最开始写的代码是没错的。
LiuYinChina 2013-05-06
  • 打赏
  • 举报
回复
http://download.csdn.net/detail/robertbaker/5125457
笨笨仔 2013-05-06
  • 打赏
  • 举报
回复
你的思路存在缺陷。 此种情况最好使用事件驱动方式进行,使用消息机制在线程间传递,主线程可使用状态机,逐一关闭工作线程后再结束自己。
土掉渣 2013-05-06
  • 打赏
  • 举报
回复
多谢“吉拔猫”的热心回复,但测试了还是不管用啊,最后ret返回值是-1,我看了下宏定义是WAIT_FAILED。 看来问题是出在子线程上面,因为发现主线程通过全局变量bExitThread[i] = TRUE;告诉子需要退出时,子线程并没有退出;
leer168 2013-05-06
  • 打赏
  • 举报
回复
LZ的代码在单CPU,单核,无超线程情况下,主线程的while+sleep是有可能让出CPU的啊,不知道为什么子线程得不到执行(如果是忙等待才会如此)。 试下这样 1.主线程设置退出标志 2.主线程等待子线程退出WaitForMultiObjects 3.大家都退出了
牧童吃五谷 2013-05-04
  • 打赏
  • 举报
回复
for(int i=0;i<20;i++) { 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); } }
ljz888666555 2013-05-03
  • 打赏
  • 举报
回复
WatitForSingleObject 等待线程退出
oyljerry 2013-05-03
  • 打赏
  • 举报
回复
先分析子线程跑到什么地方了
qiminixi 2013-05-03
  • 打赏
  • 举报
回复
看看是不是在myfunc里死循环了

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧