2016-07-06 42 views
1

我需要在类Foo中收到某个触发器事件时产生一个线程。触发器事件由Winsock服务器类接收,该类服务器引用了变量triggerEvent线程在面向对象的事件驱动的应用程序中

bool Foo::HandleEvents() 
{ 
    while (1) 
    { 
     // Other things are done at the top of this loop 

     switch (triggerEvent) 
     { 
      case 'h': 
      { 
       // I instantiate an object here to do 
       // what I need to do in the thread. 
       // I use a pointer that is a private 
       // member of Foo. 
       thingMaker = new ThingMaker(params); 

       // Spawn a new thread here calling a 
       // function of ThingMaker and using thingMaker 
       break; 
      } 
      case ...: return true; 
      default: break; 
     } 
    } 
} 

由于线程局部其在switch情况下,我无法访问它break。我不能拨打join(),因为我正在处理实时处理,不能等待线程完成,除非我知道它已经完成。

我最近问了一个关于线程here关于同样的应用程序的问题,并被告知detach()是不好的做法;我也认为我的问题太模糊了,因为提供的解决方案最终不符合我的需求,而且我的应用程序因此在架构上发生了变化。

我也试图封装线程在短生命管理器类中创建ThingMaker的实例,但无济于事。

我该如何解决这个问题?我怀疑我的主要问题是范围,但我的选择是有限的。 Foo::HandleEvents()不能被延迟,否则我会丢失关键数据。

+3

您是否考虑过一个系统,您可以控制线程生命周期,例如线程池,在该线程池中发布的代码将您的'params'发布到池监控的队列中,以便分派工作? – WhozCraig

+0

如何处理'期货'?你有C++ 11吗? – Arunmu

+1

为什么不让'thread'成为'Foo'类的成员,那么你总是可以访问它?我有一个问题,如果在触发'HandleEvent'函数时线程仍在执行,您希望发生什么?您可能需要数据成员来跟踪所有未完成的线程... –

回答

1

你可以使用一个std::map(或其他类似容器之一):

class Foo 
{ 
    bool HandleEvents(); 
    std::map<ThingMaker*, std::thread> m_map; 
}; 

bool Foo::HandleEvents() 
{ 
    while (1) 
    { 
     switch (triggerEvent) 
     { 
      case 'h': 
      { 
       thingMaker = new ThingMaker(params); 
       m_map[thingMaker] = std::thread(function_ptr, thingMaker); 
      } break; 
      case 't': // termination event trigger 
      { 
       m_map[thingMaker].second.join(); 
       m_map.erase(thingMaker); 
       delete thingMaker; 
      } break; 
      case ...: return true; 
      default: break; 
     } 
    } 
} 

因为这显然是不完整的代码,你必须调整上面的代码,以满足您的需求,但你可以在模板中交换地图的键/值,或者使用线程ID代替,如果这样会更有意义的话(例如std::map<std::thread::id, ThingMaker*>等),但是像map这样的东西可以避免迭代遍历每个线程上的数组和join如果你不一定需要一个实现一个完整的线程池实现。

注意事项:使用detach并不差,其实它相当有用;将线程信号分离到内核,一旦线程完成执行(它释放某些资源和句柄),就可以“清理”线程。当你知道你不再需要访问底层线程句柄时(比如在一个非常短暂的线程中),在线程上调用detach是很有用的。它既不坏也不好,只是一个利用的工具(如臭名昭着的goto声明)。

希望能有所帮助。

+0

真棒回答。很棒。谢谢你对'detach'的澄清。 –