我正在使用_beginthread在我的应用程序中使用多线程,并且现在要等到所有线程都完成我有全局bool,当每个线程完成时设置为true,所以我在while循环之前。必须有一个更简洁的方法吗?
由于
答案 0 :(得分:8)
您可以使用WaitForMultipleObjects等待线程在主线程中完成。
答案 1 :(得分:3)
您想要了解的是线程同步技术 - 幸运的是,MSDN上有相当多的信息可能会帮助您解决问题。你可能想要使用事件和WaitHandles这里是MSDN上的主要内容:http://msdn.microsoft.com/en-us/library/ms681924%28v=VS.85%29.aspx有很多例子。
MFC中还有一些关于同步的信息(可能会或可能不会有用,可供参考之用):http://msdn.microsoft.com/en-us/library/975t8ks0%28VS.71%29.aspx
我已经做了一些搜索,但是我很难找到一些不使用MFC实现的有用信息。这里有一个很好的教程(http://www.informit.com/library/content.aspx?b=Visual_C_PlusPlus&seqNum=149)但是,再次使用MFC。你可以看看MFC的互斥体实现虽然是一个开始。
因此,您需要熟悉同步功能和结构 - 所有这些都在MSDN上进行了介绍:http://msdn.microsoft.com/en-us/library/ms686679%28v=VS.85%29.aspx
答案 2 :(得分:2)
请改用_beginthreadex
。 _beginthread
和_beginthreadex
return a thread handle都有,但以_beginthread
开头的线程会在完成时自动关闭其句柄,因此使用它进行同步是不可靠的。
线程句柄可以与Win32的某个同步函数一起使用,例如WaitForSingleObject或WaitForMultipleObjects。
完成后,必须使用_beginthreadex
关闭CloseHandle()
返回的句柄。
答案 3 :(得分:2)
通常的方法是保留所有线程句柄,然后等待每个句柄。当句柄发出信号时,线程已完成,因此它将从线程集中删除。我使用std::set<HANDLE>
来跟踪线程句柄。在Windows中等待多个对象有两种不同的方法:
WaitForSingleObject
WaitForMultipleObjects
第一种听起来效率低下,但它实际上是两者中最直接且最不容易出错的。如果需要等待所有线程,请使用以下循环:
std::set<HANDLE> thread_handles; // contains the handle of each worker thread
while (!thread_handles.empty()) {
std::set<HANDLE> threads_left;
for (std::set<HANDLE>::iterator cur_thread=thread_handles.begin(),
last=thread_handles.end();
cur_thread != last; ++cur_thread)
{
DWORD rc = ::WaitForSingleObject(*cur_thread, some_timeout);
if (rc == WAIT_OBJECT_0) {
::CloseHandle(*cur_thread); // necessary with _beginthreadex
} else if (rc == WAIT_TIMEOUT) {
threads_left.add(cur_thread); // wait again
} else {
// this shouldn't happen... try to close the handle and hope
// for the best!
::CloseHandle(*cur_thread); // necessary with _beginthreadex
}
}
std::swap(threads_left, thread_handles);
}
使用WaitForMultipleObjects
等待线程完成比听起来要困难一些。以下将等待所有线程;但是,它一次只等待WAIT_MAXIMUM_OBJECTS
个线程。另一个选择是遍历每个线程页面。我会把这个练习留给读者;)
DWORD large_timeout = (5 * 60 * 1000); // five minutes
std::set<HANDLE> thread_handles; // contains the handle of each worker thread
std::vector<HANDLE> ary; // WaitForMultipleObjects wants an array...
while (!thread_handles.empty()) {
ary.assign(thread_handles.begin(), thread_handles.end());
DWORD rc = ::WaitForMultipleObjects(std::min(ary.size(), WAIT_MAXIMUM_OBJECTS),
&ary[0], FALSE, large_timeout);
if (rc == WAIT_FAILED) {
// handle a failure case... this is usually something pretty bad
break;
} else if (rc == WAIT_TIMEOUT) {
// no thread exited in five minutes... this can be tricky since one of
// the threads beyond the first WAIT_MAXIMUM_OBJECTS may have terminated
} else {
long idx = (rc - WAIT_OBJECT_0);
if (idx > 0 && idx < ary.size()) {
// the object at `idx` was signaled, this means that the
// thread has terminated.
thread_handles.erase(ary[idx]);
::CloseHandle(ary[idx]); // necessary with _beginthreadex
}
}
}
这不是很漂亮,但应该有效。如果您相信所有线程都会退出并且不介意等待它们,那么您可以使用WaitForMultipleObjects(ary.size(), &ary[0], TRUE, INFINITE)
。这通常不是很安全,但是因为失控的线程会导致应用程序无限期阻塞和只有当ary.size()
小于MAXIMUM_WAIT_OBJECTS
时它才会起作用。
当然另一个选择是找到一个线程池实现并改为使用它。编写线程代码并不是很有趣,特别是一旦你必须在野外支持它。请考虑使用类似boost::thread_group
的内容。
答案 4 :(得分:1)
您可以使用boost :: thread对象。在对象上调用join
,它将等待线程完成。
答案 5 :(得分:0)
Windows为一个线程提供事件以通知另一个线程。开箱即用Visual C ++仅在MFC内提供对事件的支持。对于便携式非MFC版本,请检查Boost库的thread management classes。尽管它们不能直接访问所有Windows API的功能,但它们使启动和等待线程变得更加容易。