我在我的应用程序中使用了多线程和 _beginthread。目前为止,为了等待所有的线程完成,我使用全局布尔变量,每个线程完成后都会将其设置为 true,然后我进入 while 循环等待。一定有更简洁的方法来实现这个吧?
谢谢
我在我的应用程序中使用了多线程和 _beginthread。目前为止,为了等待所有的线程完成,我使用全局布尔变量,每个线程完成后都会将其设置为 true,然后我进入 while 循环等待。一定有更简洁的方法来实现这个吧?
谢谢
您可以使用WaitForMultipleObjects函数在主线程中等待线程完成。
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
等类似工具。我进行了一些搜索,但很难找到一些有用的信息,这些信息不使用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。
_beginthreadex
替代。无论是 _beginthread
还是 _beginthreadex
都返回线程句柄,但是由 _beginthread
启动的线程在完成后会自动关闭其句柄,因此在同步方面使用它不可靠。_beginthreadex
返回的句柄必须使用 CloseHandle()
关闭。join
,它将等待线程完成。Windows 提供了一种线程间通知的事件机制。Visual C++ 默认只在 MFC 中提供对事件的支持。如果需要一个可移植的、非 MFC 版本的事件机制,可以查看 Boost 库中的 线程管理类。它们使得启动和等待线程变得更加容易,尽管它们并不直接提供对所有 Windows API 功能的访问。