1

我有一个ChunkManager有几个(应该是)异步方法的类。这些方法在我的游戏引擎中处理任务,例如在不同的线程上加载地图块(类似于 Minecraft),以免完全停止主线程(它们是冗长的操作)这是其中一种方法:

void ChunkManager::asyncRenderChunks(){

    boost::thread loadingThread(&ChunkManager::renderChunks,this);
}

renderChunks 看起来像:

void ChunkManager::renderChunks(){
activeChunksMutex->lock();
      for(int z=0; z < CHUNK_MAX; z=z+1)
      {
        for(int y=0; y < CHUNK_MAX; y=y+1)
        {
            for(int x=0; x < CHUNK_MAX; x=x+1)
            {

            activeChunks[x][y][z]->Render(scnMgr);

            }
        }
    }
    activeChunksMutex->unlock();
}

这应该有效,对吧?但是,当它运行时它会崩溃。我有一种感觉,这与我在创建线程后对线程所做的事情有关,因为如果我把

加载线程.join();

在上述方法中,它工作正常,但主线程被暂停,因为显然它只是在等待新线程完成,有效地将我带回第一方。有什么建议吗?抱歉,如果这是一个迟钝的问题,我对线程的概念不熟悉。谢谢。

更新(2013 年 4 月 9 日):我找到了这个宝石:http ://threadpool.sourceforge.net/ ..并 解决了我的问题!

4

2 回答 2

0

如果你可以加入线程,它必须是可加入的。

正如文档中所说:

boost::thread代表执行线程的对象被销毁时,如果线程是可连接的,程序就会终止

您创建了一个本地thread对象并立即让它超出范围:它在ChunkManager::asyncRenderChunks返回时被销毁。

任何一个:

  • 使其成为分离的(不可连接的)线程

    void ChunkManager::asyncRenderChunks() {
        boost::thread loadingThread(&ChunkManager::renderChunks,this);
        loadingThread.detach();
    }
    
  • 或在其他地方创建thread对象并使其保持活动状态

    class ChunkManager {
        boost::thread renderingThread;
        bool renderChunkWork;       // work to do flag
        Chunk activeChunks[CHUNK_MAX][CHUNK_MAX][CHUNK_MAX];
        boost::mutex activeChunksMutex;
        boost::condition_variable activeChunksCV;
    
        bool shutdown;              // shutdown flag
    
        void renderChunks() {
            for(int z=0; z < CHUNK_MAX; ++z)
                for(int y=0; y < CHUNK_MAX; ++y)
                    for(int x=0; x < CHUNK_MAX; ++x)
                        activeChunks[x][y][z]->Render(scnMgr);
        }
    
        void renderChunkThread() {
            boost::unique_lock<boost::mutex> guard(activeChunksMutex);
            while (true) {
                while (!(renderChunkWork || shutdown))
                    activeChunksCV.wait(guard);
    
                if (shutdown)
                    break;
                renderChunks();
                doRenderChunks = false;
            }
        }
    
    public:
        ChunkManager()
            : loadingThread(&ChunkManager::renderChunkThread, this),
            renderChunkWork(false), shutdown(false)
        {}
    
        ~ChunkManager() {
            { // tell the rendering thread to quit
                boost::unique_lock<boost::mutex> guard(activeChunksMutex);
                renderChunkShutdown = true;
                activeChunksCV.notify_one();
            }
            renderingThread.join()
        }
    
        void asyncRenderChunks() {
            boost::unique_lock<boost::mutex> guard(activeChunksMutex);
            if (!renderChunkWork) {
                renderChunkWork = true;
                activeChunksCV.notify_one();
            }
        }
    };
    

注意。一般来说,动态创建线程不如预先创建线程好,然后在有事可做时唤醒它们。它避免在最后一个调用完成之前弄清楚如何处理第二个调用asyncRenderChunks(启动第二个线程?块?),并移动与线程创建相关的延迟。


关于对象生命周期的注意事项

在这段代码中意识到这一点很重要:

void ChunkManager::asyncRenderChunks() {
    SomeType myObject;
}

该实例myObject将被创建然后立即销毁

于 2013-04-09T16:22:16.130 回答
0

它崩溃了,因为在当前版本中Boost.Thread,您必须加入()一个线程或detach()它 - 否则~thread 会终止程序~thread(在用于自动调用的早期版本中detach()。)

因此,如果您不想加入线程 - 只需将其分离:

boost::thread loadingThread(&ChunkManager::renderChunks,this);
loadingThread.detach();
于 2013-04-09T17:40:46.237 回答