3

我正在寻找一种方法(最好使用 boost 线程),如果线程没有加入,则中断它。我启动了多个线程,并希望在 200 毫秒内结束其中的任何一个。我尝试过这样的事情

boost::thread_group tgroup;
tgroup.create_thread(boost::bind(&print_f));
tgroup.create_thread(boost::bind(&print_g));
boost::this_thread::sleep(boost::posix_time::milliseconds(200));
tgroup.interrupt_all();

现在这工作了,所有线程在 200 毫秒后结束;但是,如果它们在 200 毫秒之前完成,我想尝试加入这些线程,如果在一定时间内没有完成,有没有办法加入和中断?

编辑:我需要在超时之前加入的原因:

我正在创建一个速度非常重要的服务器。不幸的是,我必须向其他服务器请求一些信息。所以我想并行进行这些调用,并尽快完成。如果服务器花费的时间太长,我必须忽略来自该服务器的信息,并在没有它的情况下继续。所以我的超时时间是我可以等待的最长时间。当收到所有响应时,能够继续沉思,而不是等待超时计时器,这对我来说是非常有益的。所以我的程序将:

- 获取客户的请求。

-解析信息。

创建线程

- 将信息发送到多个其他服务器。

- 从服务器获取信息。

- 将来自服务器的信息放在共享队列中。

结束线程

-从共享队列中解析信息。

- 将信息返回给客户

4

2 回答 2

3

如果您使用的是最新的 Boost 和 C++11,请使用try_join_for()( http://www.boost.org/doc/libs/1_53_0/doc/html/thread/thread_management.html#thread.thread_management.thread.try_join_for)。否则,请使用timed_join()http://www.boost.org/doc/libs/1_53_0/doc/html/thread/thread_management.html#thread.thread_management.thread.timed_join)。

于 2013-04-10T14:56:42.623 回答
3

您想要使用的可能是一组范围线程,并在超时后对所有剩余线程调用终止。不幸的是,线程组和作用域线程不能一起使用。

线程组类实际上是一个非常简单的容器:如果您还没有指向它的指针,则无法删除它的线程,并且您无法获得指向已由组创建的线程的指针。类 API 也没有提供太多。在您的情况下,这有点妨碍管理。

其余的解决方案依赖于在组外创建线程,并让每个线程在完成之前执行特定任务。它可能:

  • 从组中删除自己,
  • 然后将自己添加到另一个组

管理线程将不得不调用join_all后面的组,并像以前一样处理前者。

using namespace boost;
void thread_end(auto &thmap, thread_group& t1, thread_group& t2, auto &task){
    task();
    thread *self = thmap[this_thread::get_id()];
    t1.remove_thread(&self);
    t2.add_thread(&self);
}

 std::map<thread::id, thread *> thmap;
thread_group trunninggroup;
thread_group tfinishedgroup;
thread *th;
th = new thread(
    bind(&thread_end, thmap, trunninggroup, tfinishedgroup, bind(&print_f)));
thmap[th->get_id()] = th;
trunninggroup.add_thread(th);
th = new thread(
    bind(&thread_end, thmap, trunning_group, tfinishedgroup, bind(&print_g)));
thmap[th->get_id()] = th;
trunninggroup.add_thread(th);
boost::this_thread::sleep(boost::posix_time::milliseconds(200));
tfinishedgroup.join_all();
trunninggroup.interrupt_all();

但是,如果您确实希望在线程实际发生时通知管理线程线程结束(而且我不确定它是否会做任何有用的事情),这并不理想。获得通知的解决方案可能是:

  • 如上所述进行组迁移
  • 然后触发管理线程正在执行的条件变量timed_wait

但是您必须进行一些时间计算以跟踪收到通知后的剩余时间,并在剩下的时间恢复睡眠。这将完全取决于用于该任务的 Duration 类。

更新

从大局来看,我会尝试一种完全不同的方法:我不认为终止一个已经完成的线程是一个问题,所以我会将它们全部留在组中,并使用组来创建它们,作为你的代码演示它。

但是,我会在所有线程完成后或超时后尝试唤醒管理线程。这thread_group仅靠该类提供的内容是不可行的,但可以通过定制的信号量或boost::barrier允许定时等待的修补版本来完成。

基本上,您为组中的线程数加一(主线程)设置障碍,并让主线程时间等待它。每个工作线程完成其工作,完成后,将其结果发布到队列和wait屏障上。如果所有工作线程都完成了他们的任务,每个人都会等待并触发屏障。

然后主线程(以及所有其他线程,但没关系)唤醒并可以通过终止组并处理结果来继续。否则,它将在超时时被唤醒并做同样的事情。

的补丁boost::barrier应该不会太难,你应该只需要复制wait方法并将里面的条件变量替换为waita timed_wait(我没有看代码,这个假设可能完全有道理)。否则,我为这个问题提供了一个示例信号量实现,也应该不难修补。

最后一点考虑:终止线程通常不是最好的方法。相反,您应该尝试向它们发出中止线程的信号,并等待它们,或者以某种方式让它们将未完成的任务传递给应该连续清理的辅助线程。然后,您的线程组将准备好处理下一个任务,并且您不必一直销毁和创建线程,这是一项代价高昂的操作。它将需要在应用程序的上下文中形式化任务的概念,并使线程在循环上运行以获取新任务并处理它们。

于 2013-04-10T15:25:58.020 回答