WaitForMultipleObjects的奇怪问题

ltcsky 2005-06-22 12:16:19

程序是2k下的服务,在线程里再开多个子线程
handle* ht=new handle[count]
for(int i=0;i<count;i++)
{
ht[i]=_beghinthread(...)//
//线程里用_endthread退出
}
WaitForMultipleObjects(count,ht,TRUE,INFINITE);
总是只要有一个线程结束就返回了,但用CreateThread和ExitThread好像就没问题
是不是_endthread不改变线程状态啊,更奇怪的是
for(int i=0;i<count;i++)
{
waitforsingleobject(ht[i],INFINITE);
}
这样也没问题,不明白为什么,有人遇到过这种情况么?求解!!!(最好能实际测试一下再回答)
...全文
490 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
goodboyws 2005-06-26
  • 打赏
  • 举报
回复
给偶的分少了点:(
ltcsky 2005-06-25
  • 打赏
  • 举报
回复
to gboy
呵呵,你的方法我已用过的确可以,但我用CreateThread会有内存泄露,因为线程函数里用到了std库里的东西,还是谢谢你,结帖了...
gbstar2021 2005-06-24
  • 打赏
  • 举报
回复
const int nCount=10;
HANDLE h[nCount];

for(int i=0;i<nCount;i++)
{
DWORD nThreadID;
h[i]= ::CreateThread(NULL,0,thead_fun,(LPVOID)i,0,&nThreadID);

}

WaitForMultipleObjects(nCount,h,TRUE,INFINITE); // 等待结束

// 需要关闭所有的 handles
for(i=0;i<nCount;i++)
CloseHandle(h[i]);


这样写就没有问题了
gbstar2021 2005-06-24
  • 打赏
  • 举报
回复
这里不是 WaitForMultipleObjects 的问题,问题应该在这里,_beghinthread 启动的线程结束之后,会自动调用 CloseHandle 关闭掉句柄, 这样WaitForMultipleObjects 就会拿着个无效的 handle 傻等。

因为线程句柄是使用引用计数维护生命期,引用计数为 0 的时候就已经不能进行操作了。

所以CreateThread没有问题
Sander 2005-06-24
  • 打赏
  • 举报
回复
哦,我看错,
其实可以用event代替呀, 退出时Setevnet
ltcsky 2005-06-23
  • 打赏
  • 举报
回复
to Sander()
我的目的就是要所有线程都结束后才返回呀,WaitForAll应设为True吧

看来没有办法准确判断句柄是否有效, GetHandleInformation()好像不行
再等等看有没有高手...
Sander 2005-06-23
  • 打赏
  • 举报
回复
WaitForMultipleObjects(count,ht,TRUE,INFINITE);
总是只要有一个线程结束就返回了,但用CreateThread和ExitThread好像就没问题
--------------------
应该是
WaitForMultipleObjects(count,ht,FALSE,INFINITE);
goodboyws 2005-06-23
  • 打赏
  • 举报
回复
BOOL GetHandleInformation(
HANDLE hObject, // handle to object
LPDWORD lpdwFlags // handle properties
);
Parameters
hObject
[in] Specifies a handle to an object. The GetHandleInformation function obtains information about this object handle.
You can specify a handle to one of the following types of objects: access token, event, file, file mapping, job, mailslot, mutex, pipe, printer, process, registry key, semaphore, serial communication device, socket, thread, or waitable timer.

Windows 2000: This parameter can also be a handle to a console input buffer or a console screen buffer.

lpdwFlags
[out] Pointer to a variable that receives a set of bit flags that specify properties of the object handle. The following flags are defined:
Value Meaning
HANDLE_FLAG_INHERIT
If this flag is set, a child process created with the bInheritHandles parameter of CreateProcess set to TRUE will inherit the object handle.

HANDLE_FLAG_PROTECT_FROM_CLOSE
If this flag is set, calling the CloseHandle function will not close the object handle.

如上, GetHandleInformation没有判断句柄有效性的功能
goodboyws 2005-06-23
  • 打赏
  • 举报
回复
to lianglp()

GetHandleInformation用来做两种判断,一个是继承HANDLE,一个是CloseHandle保护,即禁止调用CloseHandle关闭句柄,详细情况可以看Msdn

“如果用户在关闭内核句柄之前调用了Waitfor...()函数,如果此时用户调用 Closehandle()关闭它。
这时如果线程没有退出......”
CloseHandle仅仅是将线程对象的引用计数减一,当线程创建以后,它的引用计数为2,退出线程减一,
关闭句柄减一,如果关闭内核句柄而没有退出线程,句柄是有效的。
lianglp 2005-06-23
  • 打赏
  • 举报
回复
GetHandleInformation()可以作下判断。。。
如果返回false应该可以判断它无效。

不过楼说得
“_endthread关闭了句柄,句柄已经无效,所以WaitForMultipleObjects返回WAIT_FAILED”
不太确切吧!

如果用户在关闭内核句柄之前调用了Waitfor...()函数,如果此时用户调用 Closehandle()关闭它。
这时如果线程没有退出,是不会返回的,除非超时。
zPerry 2005-06-23
  • 打赏
  • 举报
回复
建议使用_beginthreadex
MSDN里说
It is safer to use _beginthreadex than _beginthread. If the thread spawned by _beginthread exits quickly, the handle returned to the caller of _beginthread may be invalid or, worse, point to another thread. However, the handle returned by _beginthreadex has to be closed by the caller of _beginthreadex, so it is guaranteed to be a valid handle if _beginthreadex did not return an error.
xing_xing_xing 2005-06-22
  • 打赏
  • 举报
回复
这样使用可以
#include <windows.h>
#include <stdio.h>
#include <process.h>

unsigned Counter;
unsigned __stdcall SecondThreadFunc( void* pArguments )
{
printf( "In second thread...\n" );

while ( Counter < 1000000 )
Counter++;

_endthreadex( 0 );
return 0;
}

int main()
{
HANDLE hThread;
//unsigned threadID;

printf( "Creating second thread...\n" );

int count = 5;
unsigned* threadID=new unsigned[count];
for(int i=0;i<count;i++)
{
threadID[i]=_beginthreadex( NULL, 0, &SecondThreadFunc, NULL, 0, &threadID[i] );
}

WaitForMultipleObjects(count,(HANDLE*)threadID,TRUE,INFINITE);
printf( "Counter should be 1000000; it is-> %d\n", Counter );
}
ltcsky 2005-06-22
  • 打赏
  • 举报
回复
多谢各位大侠,问题已解决,再问一下有没有函数判断句柄是否有效,马上就结帖!
DentistryDoctor 2005-06-22
  • 打赏
  • 举报
回复
_endthread关闭了句柄,句柄已经无效,所以WaitForMultipleObjects返回WAIT_FAILED
goodboyws 2005-06-22
  • 打赏
  • 举报
回复
这是Msdn里的原话,如果任何一个句柄被关闭, WaitForMultipleObjects会返回WAIT_FAILED ,调用GetLastError()会得到ERROR_INVALID_HANDLE, 因为_endthread自动关闭了句柄,WaitForMultipleObjects认为句柄非法,所以造成了以上问题
goodboyws 2005-06-22
  • 打赏
  • 举报
回复
endthread automatically closes the thread handle (whereas _endthreadex does not). Therefore, when using _beginthread and _endthread, do not explicitly close the thread handle by calling the Win32CloseHandle API. This behavior differs from the Win32ExitThread API.

15,471

社区成员

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

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