windows 检查线程是否完成的正确方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3180164/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Correct way of checking if threads are done?
提问by jmasterx
I'm using multithreading in my application with _beginthread and right now to wait until all threads are done I have global bools that get set to true as each thread completes so I'm in a while loop until then. There must be a cleaner way of doing this?
我在我的应用程序中使用 _beginthread 使用多线程,现在等待所有线程完成我有全局布尔值在每个线程完成时设置为 true 所以我在 while 循环中直到那时。必须有一种更清洁的方法来做到这一点?
Thanks
谢谢
回答by cpx
You can use WaitForMultipleObjectsto wait for the threads to finish in primary thread.
您可以使用WaitForMultipleObjects等待线程在主线程中完成。
回答by RobS
What you want to have a look at is thread synchronization techniques - luckily there is quite a bit of information on MSDN which can probably help you out. It's likely you'll want to use Events and WaitHandles here's the main stuff on MSDN: http://msdn.microsoft.com/en-us/library/ms681924%28v=VS.85%29.aspxthere are a number of examples.
您想了解的是线程同步技术 - 幸运的是,MSDN 上有很多信息可以帮助您。您可能想要使用事件和等待句柄,这是 MSDN 上的主要内容:http: //msdn.microsoft.com/en-us/library/ms681924%28v=VS.85%29.aspx有很多例子。
There's also some info on synchronization in MFC (which may or may not prove helpful, added for reference purposes): http://msdn.microsoft.com/en-us/library/975t8ks0%28VS.71%29.aspx
还有一些关于 MFC 同步的信息(可能有用也可能没有用,添加以供参考):http: //msdn.microsoft.com/en-us/library/975t8ks0%28VS.71%29.aspx
I've done a bit of searching, but I've had a hard time trying to track down some helpful info for you which doesn't use the MFC implementation. There's a good tutorial here ( http://www.informit.com/library/content.aspx?b=Visual_C_PlusPlus&seqNum=149) but, again, using MFC. You could take a look at the MFC implementation of mutexes though as a start.
我已经做了一些搜索,但我很难找到一些对您有用的信息,这些信息不使用 MFC 实现。这里有一个很好的教程(http://www.informit.com/library/content.aspx?b=Visual_C_PlusPlus&seqNum=149)但是,再次使用 MFC。作为开始,您可以查看互斥锁的 MFC 实现。
So, you'd need to get familiar with synchronization functions and structures - all covered here on MSDN: http://msdn.microsoft.com/en-us/library/ms686679%28v=VS.85%29.aspx
因此,您需要熟悉同步功能和结构 - MSDN 上都有介绍:http: //msdn.microsoft.com/en-us/library/ms686679%28v=VS.85%29.aspx
回答by atzz
Use _beginthreadex
instead. Both _beginthread
and _beginthreadex
return a thread handle, but the thread started with _beginthread
automatically closes its handle when it finishes, so using it for synchronization is not reliable.
使用_beginthreadex
来代替。双方_beginthread
并_beginthreadex
返回一个线程处理,而是开始与线程_beginthread
当它完成自动关闭其句柄,因此使用它进行同步是不可靠的。
Thread handle can be used with one of the synchronization functions of Win32, such as WaitForSingleObjector WaitForMultipleObjects.
线程句柄可以与 Win32 的同步函数之一一起使用,例如WaitForSingleObject或WaitForMultipleObjects。
When done, handles returned by _beginthreadex
must be closed with CloseHandle()
.
完成后,返回的句柄_beginthreadex
必须用 关闭CloseHandle()
。
回答by D.Shawley
The usual method is to keep all of the thread handles and then wait on each handle. When the handle is signaled, the thread has finished so it is removed from the set of threads. I use std::set<HANDLE>
to keep track of the thread handles. There are two different methods for waiting on multiple objects in Windows:
通常的方法是保留所有线程句柄,然后等待每个句柄。当句柄发出信号时,线程已完成,因此它从线程集中删除。我std::set<HANDLE>
用来跟踪线程句柄。在 Windows 中等待多个对象有两种不同的方法:
- Iterate over the set and call
WaitForSingleObject
with a timeout on each one - Convert the set into an array or vector and call
WaitForMultipleObjects
- 迭代集合并
WaitForSingleObject
在每个集合上调用超时 - 将集合转换为数组或向量并调用
WaitForMultipleObjects
The first sounds inefficient, but it is actually the most direct and least error prone of the two. If you need to wait for all of the threads, then use the following loop:
第一个听起来效率低下,但它实际上是两者中最直接和最不容易出错的。如果您需要等待所有线程,则使用以下循环:
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);
}
Using WaitForMultipleObjects
to wait for the threads to finish is a bit more difficult than it sounds. The following will wait for all of the threads; however, it only waits for WAIT_MAXIMUM_OBJECTS
threads at a time. Another options is to loop over each page of threads. I'll leave that exercise to the reader ;)
使用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
}
}
}
This isn't exactly pretty but it should work. If you trust that all of your threads will exit and don't mind waiting for them, then you can use WaitForMultipleObjects(ary.size(), &ary[0], TRUE, INFINITE)
. This usually isn't very safe though since a runaway thread will cause your application to block indefinitely andit will only work if ary.size()
is less than MAXIMUM_WAIT_OBJECTS
.
这不是很漂亮,但它应该可以工作。如果您相信所有线程都会退出并且不介意等待它们,那么您可以使用WaitForMultipleObjects(ary.size(), &ary[0], TRUE, INFINITE)
. 这通常不是很安全,因为失控的线程会导致您的应用程序无限期阻塞,并且只有在ary.size()
小于MAXIMUM_WAIT_OBJECTS
.
Of course the other option is to find a thread pool implementation and use it instead. Writing threading code is not really a lot of fun especially once you have to support it in the wild. Consider using something like boost::thread_group
instead.
当然,另一种选择是找到一个线程池实现并使用它。编写线程代码并不是很有趣,尤其是当您必须支持它时。考虑使用类似的东西boost::thread_group
。
回答by Anthony
You can use boost::thread objects. Call join
on the object and it will wait for the thread to finish.
您可以使用 boost::thread 对象。调用join
该对象,它将等待线程完成。
回答by Panagiotis Kanavos
Windows provides events for one thread to notify another. Out of the box Visual C++ provides support for events only inside MFC. For a portable, non-MFC version, check the thread management classesof the Boost library. They make launching and waiting for threads a lot easier, although they don't provide direct access to all of Windows API's functionality.
Windows 为一个线程提供事件以通知另一个线程。开箱即用的 Visual C++ 仅支持 MFC 内部的事件。对于可移植的非 MFC 版本,请检查Boost 库的线程管理类。尽管它们不提供对所有 Windows API 功能的直接访问,但它们使启动和等待线程变得更加容易。