主进程如何等待多个线程退出?

shuangquan 2009-04-11 10:58:27
线程的实现继承了CWinThread.
在主进程里启动了多个线程,而主进程要等待线程结束后关闭程序。
如何用waitmultipleobject?
谢谢。
...全文
1717 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
bragi523 2009-04-30
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 cnzdgs 的回复:]
WaitForMultipleObjects用在这里很不合适,如果一定要用WaitForMultipleObjects,需要创建线程时先让线程休眠,将返回的指针保存起来,并将m_bAutoDelete设置为FALSE,然后再唤醒线程,在等待线程结束时,要定义一个HANDLE型数组,从各个线程对象指针中取出线程句柄,逐个填到数组里面,然后用WaitForMultipleObjects等待,然后再逐个关闭句柄、销毁对象。注意,句柄数不能超过64个。这种做法还不如用WaitForSingleObject逐个等待…
[/Quote]

学习!
哈利路亚1874 2009-04-30
  • 打赏
  • 举报
回复
这么简单的问题,我觉得很好解决啊!直接传入INFINITE参数!
捕鲸叉 2009-04-28
  • 打赏
  • 举报
回复
可以用事件
ky310 2009-04-21
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 cnzdgs 的回复:]
WaitForMultipleObjects用在这里很不合适,如果一定要用WaitForMultipleObjects,需要创建线程时先让线程休眠,将返回的指针保存起来,并将m_bAutoDelete设置为FALSE,然后再唤醒线程,在等待线程结束时,要定义一个HANDLE型数组,从各个线程对象指针中取出线程句柄,逐个填到数组里面,然后用WaitForMultipleObjects等待,然后再逐个关闭句柄、销毁对象。注意,句柄数不能超过64个。这种做法还不如用WaitForSingleObject逐个等待…
[/Quote]
顶,不过我很喜欢用CWinThread
Cat_Of_9Life 2009-04-21
  • 打赏
  • 举报
回复
简单些,设个全局event,在线程循环里等待event,等到就退出
WQ 2009-04-17
  • 打赏
  • 举报
回复
超过最大值的解决方法
To wait on more than MAXIMUM_WAIT_OBJECTS handles, use one of the following methods:

Create a thread to wait on MAXIMUM_WAIT_OBJECTS handles, then wait on that thread plus the other handles. Use this technique to break the handles into groups of MAXIMUM_WAIT_OBJECTS.


Call RegisterWaitForSingleObject to wait on each handle. A wait thread from the thread pool waits on MAXIMUM_WAIT_OBJECTS registered objects and assigns a worker thread after the object is signaled or the time-out interval expires.
ahao 2009-04-17
  • 打赏
  • 举报
回复
boost::thread_group grp;
grp.create_thread(xxx);
grp.create_thread(yyy);
grp.create_thread(zzz);
grp.join_all();


cnzdgs 2009-04-16
  • 打赏
  • 举报
回复
WaitForMultipleObjects用在这里很不合适,如果一定要用WaitForMultipleObjects,需要创建线程时先让线程休眠,将返回的指针保存起来,并将m_bAutoDelete设置为FALSE,然后再唤醒线程,在等待线程结束时,要定义一个HANDLE型数组,从各个线程对象指针中取出线程句柄,逐个填到数组里面,然后用WaitForMultipleObjects等待,然后再逐个关闭句柄、销毁对象。注意,句柄数不能超过64个。这种做法还不如用WaitForSingleObject逐个等待更简单,而且没有64个句柄的限制。
比较好一点的方式是让CWinThread类自己来处理释放,程序中不保存指针和句柄,在线程退出之前给主窗口或主线程Post一个消息,主线程中进行计数,当消息数量等于创建的线程总数时则说明所有线程都以执行完毕。
CWinThread用起来比较麻烦,如果不使用消息,最好不要用它。
wenyongjie 2009-04-16
  • 打赏
  • 举报
回复
MARK
stivenjia 2009-04-16
  • 打赏
  • 举报
回复
如果使用事件机制,WaitForMultipleObjects能处理MAXIMUM_WAIT_OBJECTS/2个事件,如果你想处理的更多的事件哦完蛋了
该函数不支持。(实现起来超简单)

使用消息控制法,为每个线程开辟2-3个消息队列例如:输入队列,回执队列。
如果你的Main Process想让T1结束就向T1发送一个结束消息到它的输入队列之后Main Process检测回执队列等待T1处理结果。
此法为上上策。
但是如果一个进程同时管理着T1、T2而T1又想和T2进行交互如何实现呢,这里采用“V型消息队列”,T1和T2通信先让T1把消息
寄发给Main Process,Main Process再将该消息发送给T2。
但是该方法实现起来难度还算可以(依个人水平决定)

biweilun 2009-04-16
  • 打赏
  • 举报
回复
WaitForMultipleObjects不就OK了,那么麻烦干嘛。多个内核对象一起等待
qrlvls 2009-04-16
  • 打赏
  • 举报
回复
直接 WaitForSingleObject 线程句柄就可以了
前提是你没有对该线程 CloseHandle
  • 打赏
  • 举报
回复
帮顶
Ei 2009-04-15
  • 打赏
  • 举报
回复
DWORD WaitForMultipleObjects(
  DWORD nCount,
  const HANDLE* lpHandles,
  BOOL bWaitAll,
  DWORD dwMilliseconds
  );
  当WaitForMultipleObjects等到多个内核对象的时候,如果它的bWaitAll 参数设置为false。其返回值减去WAIT_OBJECT_0 就是参数lpHandles数组的序号。如果同时有多个内核对象被出发,这个函数返回的只是其中序号最小的那个。
捕鲸叉 2009-04-15
  • 打赏
  • 举报
回复
对每个子线程发事件。子线程退出时设置另一个事件。不知行不行,你试试
zyq5945 2009-04-11
  • 打赏
  • 举报
回复
这是我的一个程序的部分代码
=============================
int i,j,k;
HANDLE *m_pHandle=NULL;


m_pHandle=new HANDLE[p->m_nCount];
for(i=0;i<p->m_nCount;i++)
{
//CloseHandle(m_pHandle[i]);
m_pHandle[i]=NULL;
}
k=0;
for(i=0;i<p->m_nCount;i++)
{
if(!ftp[i].b)
{
if(p->m_bSDTC&&p->m_brSDTC)
{
m_pHandle[k++]=CreateThread( NULL, 0, p->SDTCThread, &ftp[i], 0, NULL );
}
//m_pHandle[k++]=CreateThread( NULL, 0, p->SDTCThread &ftp[i], 0, NULL );

else
{
m_pHandle[k++]=CreateThread( NULL, 0, p->MThread, &ftp[i], 0, NULL );
}
}
}
k--;


n[0]=k;
m_ph[0]=m_pHandle;

WaitForMultipleObjects(k,m_pHandle,TRUE,3000); //无限等待可以用infinite
delete m_pHandle;
ylywyn136 2009-04-11
  • 打赏
  • 举报
回复
呵呵.肯定能满足你
ylywyn136 2009-04-11
  • 打赏
  • 举报
回复
CEvent 类提供了对事件的支持。事件是一个允许一个线程在某种情况发生时,唤醒另外一个线程的同步对象。事件告诉线程何时去执行某一给定的任务,从而使多个线程流平滑。例如在某些网络应用程序中,一个线程(记为A)负责监听通信端口,另一个线程(记为B)负责更新用户数据。通过使用CEvent类,线程A可以通知线程B何时更新用户数据,这样线程B可以尽快地更新用户数据。每一个CEvent对象可以有两种状态:有信号状态(signaled)和无信号状态(nonsignaled)。线程监视位于其中的CEvent类对象的状态,并在相应的时候采取相应的操作。 在MFC中,CEvent类对象有两种类型,分别是所谓的人工事件和自动事件。对于自动事件,当其获得信号后,就会释放下一个可用的线程。一个自动 CEvent对象在被至少一个线程释放后会自动返回到无信号状态;而人工事件对象获得信号后,释放所有可利用线程,直到调用成员函数ReSetEvent ()将其设置为无信号状态时为止。注意,在创建CEvent类的对象时,默认创建的是自动事件。
CEvent的各成员函数的原型与参数说明如下。
CEvent(BOOL bInitiallyOwn = FALSE,BOOL bManualReset = FALSE,LPCTSTR lpszName = NULL,LPSECURITY_ATTRIBUTES lpsaAttribute = NULL );

bInitiallyOwn:若bInitiallyOwn为TRUE,则使CMultilock类对象和CSingleLock类对象的线程可用;否则,要访问资源的线程必须等待。该参数的默认值为FALSE。bManualReset:指定要创建的CEvent对象是属于手工事件还是自动事件。为TRUE,则为手工事件,否则为自动事件。该参数默认值为FALSE。lpszName:指定要创建的事件对象的名,如果该事件对象将跨进程使用,则此参数不能为NULL。如果该参数和一个已经存在的CEvent对象相同,则该构造函数返回一个对这个已存在对象的引用;如果参数和一个已存在的非CEvent类的同步对象(如CMutex)相同,则对象创建失败;lpsaAttribute:指向SECURITY_ATTRIBUTES结构的指针,该参数决定要创建的事件对象的安全属性,一般置为NULL。在事件对象建成后,可以调用其成员函数来改变其状态。
BOOL CEvent::SetEvent ();

将CEvent类对象的状态设置为有信号状态,并且释放所有等待的线 程;如果该事件是人工事件,则CEvent类对象保持为有信号状态,直到调用成员函数ResetEvent()将其重新设为无信号状态时为止,这样该事件 就可以释放多个线程;如果CEvent类对象为自动事件,则在SetEvent()将事件设置为有信号状态后,CEvent类对象由系统自动重置为无信号 状态,除非一个线程被释放。如果该函数执行成功,则返回非零值,否则返回零。
BOOL CEvent::ResetEvent();

该函数将事件的状态设置为无信号状态,并保持该状态直至SetEvent()被调用时为止。由于自动事件是由系统自动重置,故自动事件不需要调用该函数。如果该函数执行成功,返回非零值,否则返回非零。
BOOL CEvent::PulseEvent()

发送一个事件脉冲,该函数完成一系列操作后才返回。对于自动事件,PulseEvent()将事件设置为有信号状态,等待一个线程被释放,将事件重置为无信号状态,然后PulseEvent()返回;对于人工事件,则将等待该事件的所有线程被释放,事件被自动重置为无信号状态,然后PulseEvent()返回。一个CEvent对象在线程中被创建后,自动处于无信号状态,但在另一个线程中可以调用Win32 API WaitForSingleObject()函数来监视其状态。该函数的原型及参数说明如下:
DWORD WaitForSingleObject(HANDLE hHandle,DWORD dwMilliseconds);
其中hHandle为指向要监视的同步对象的句柄,dwMilliseconds为监视hHandle所指向的对象所设置的超时值,单位为毫秒。当在线程的执行函数中调用该函数时,线程暂时挂起,系统监视hHandle所指向的对象的状态。如果经过dwMilliseconds毫秒后,hHandle指向的对象变为有信号状态,则WaitForSingleObject()返回,线程被释放,且返回值为WAIT_TIMEOUT;
如果在挂起的dwMilliseconds毫秒内,线程所等待的对象在某一时刻变为有信号,则该函数立即返回,返回值为WAIT_OBJECT_0。参数dwMilliseconds有两个具有特殊意义的值:0和INFINITE。若为0,则该函数立即返回;若为INFINITE,则线程一直被挂起,直到hHandle所指向的对象变为有信号状态时为止。如果CEvent对象为自动事件,则当WaitForSingleObject(hHandle,INFINITE)返回时,自动把CEvent对象重置为无信号状态。CEvent::SetEvent()把对象设置为有信号状态,释放等待的线程。CEvent::ResetEvent()把对象设置为无信号状态,程序在WaitForSingleObject(hHandle,INFINITE)处等待。例程9 MultiThread9建立一个基于对话框的工程MultiThread9,在对话框IDD_MULTITHREAD9_DIALOG中加入一个按钮和两个编辑框控件,按钮的ID为IDC_WRITEW,标题为“写'W’”;两个编辑框的ID分别为IDC_W和IDC_D,属性都选中Read-only;
在MultiThread9Dlg.h文件中声明两个线程函数:
UINT WriteW(LPVOID pParam);
UINT WriteD(LPVOID pParam);
使用ClassWizard分别给IDC_W和IDC_D添加CEdit类变量m_ctrlW和m_ctrlD;
在MultiThread9Dlg.cpp文件中添加如下内容:
为了文件中能够正确使用同步类,在文件开头添加#include "afxmt.h"
定义事件对象和一个字符数组,为了能够在不同线程间使用,定义为全局变量。
CEvent eventWriteD;
char g_Array[10];
添加线程函数:
UINT WriteW(LPVOID pParam)
{
CEdit *pEdit=(CEdit*)pParam;
pEdit->SetWindowText("");
for(int i=0;i<10;i++)
{
g_Array[i]=''W'';
pEdit->SetWindowText(g_Array);
Sleep(1000);
}
eventWriteD.SetEvent();
return 0;}
UINT WriteD(LPVOID pParam)
{
CEdit *pEdit=(CEdit*)pParam;
pEdit->SetWindowText("");
WaitForSingleObject(eventWriteD.m_hObject,INFINITE);
for(int i=0;i<10;i++)
{
g_Array[i]=''D'';
pEdit->SetWindowText(g_Array);
Sleep(1000);
}
return 0;}
仔细分析这两个线程函数, 您就会正确理解CEvent 类。线程WriteD执行到 WaitForSingleObject(eventWriteD.m_hObject,INFINITE);处等待,直到事件eventWriteD为有信号该线程才往下执行,因为eventWriteD对象是自动事件,则当WaitForSingleObject()返回时,系统自动把eventWriteD对象重置为无信号状态。


看看这个吧,做一个人工事件,然后WaitForSingleObject
shuangquan 2009-04-11
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 zyq5945 的回复:]
这是我的一个程序的部分代码
=============================
int i,j,k;
HANDLE *m_pHandle=NULL;


m_pHandle=new HANDLE[p->m_nCount];
for(i=0;i <p->m_nCount;i++)
{
//CloseHandle(m_pHandle[i]);
m_pHandle[i]=NULL;
}
k=0;
for(i=0;i <p->m_nCount;i++)
{
if(!ftp[i].b)
{
if(p->m_bSDTC&&p->m_brSDTC)
{
m_pHandle[k++]=CreateThread( NULL, 0, p->SDTCThread, &ftp[i], 0, NULL );
}
//m_pHandle[k+…
[/Quote]

很好的例子。
如果线程的创建是继承自CWinThread类,上面的方法是否仍然可行?
另外还有个问题,非界面的程序是不是不应该继承CWinThread类。(开发的程序既要支持界面也要支持非界面,所以起线程的时候是否不应该继承自CWinThread类)
stjay 2009-04-11
  • 打赏
  • 举报
回复
CWinThread* pThread1 = AfxBeginThread(...);
CWinThread* pThread2 = AfxBeginThread(...);
HANDLE Handles[2];
Handles[0]=pThread1->m_hThread;
Handles[1]=pThread2->m_hThread;
WaitForMultipleObjects(2,Handles,TRUE,1000);

15,471

社区成员

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

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