面向对象,事件驱动的应用程序中的线程化

时间:2016-07-06 15:31:11

标签: c++ multithreading

当在类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()根本无法延迟,否则我会丢失关键数据。

1 个答案:

答案 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声明)。

希望可以提供帮助。