检查线程是否完成的正确方法?

我正在使用_beginthread在我的应用程序multithreading,现在等待,直到所有的线程完成我有全局布尔值设置为true每个线程完成,所以我在一个while循环,直到那时。 必须有一个更干净的方式来做到这一点?

谢谢

您可以使用WaitForMultipleObjects等待线程在主线程中完成。

你想看看线程同步技术 – 幸运的是有很多关于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

改用_beginthreadex_beginthread_beginthreadex 返回一个线程句柄 ,但是_beginthread启动的线程在完成时会自动关闭它的句柄,所以用它来进行同步是不可靠的。

线程句柄可以用于Win32的同步函数之一,如WaitForSingleObject或WaitForMultipleObjects 。

完成后,由_beginthreadex返回的句柄必须用CloseHandle()关闭。

通常的方法是保持所有的线程句柄,然后等待每个句柄。 当手柄发出信号时 ,线程已经完成,因此将其从线程集中移除。 我使用std::set<HANDLE>来跟踪线程句柄。 在Windows中等待多个对象有两种不同的方法:

  1. 迭代该集合,并在每一个超时的情况下调用WaitForSingleObject
  2. 将该集合转换为数组或向量并调用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东西。

Windows为一个线程提供事件以通知另一个线程。 开箱即用的Visual C ++提供了对MFC中只有事件的支持。 对于可移植的非MFC版本,请检查Boost库的线程管理类 。 他们使启动和等待线程更容易,虽然他们不提供直接访问所有的Windows API的功能。

你可以使用boost :: thread对象。 调用join对象,它将等待线程完成。