当在类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()
根本无法延迟,否则我会丢失关键数据。
答案 0 :(得分: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
声明)。
希望可以提供帮助。