【问题标题】:Concurrent Event Processing Problems并发事件处理问题
【发布时间】:2012-04-30 21:17:39
【问题描述】:

我刚开始学习一般的多线程,我知道示例应用程序(我正在研究)在使用线程时甚至可能会降低性能。使用的编译器是 GCC4.7,带有以下标志: -std=c++0x -g -O3 -Wall

因此,我正在使用 C++11 并使用 std::thread 实现。一般来说,我尝试开发跨平台,所以我在大学计算机上的 Windows 上使用 GCC4.7 以及在我的家用机器上开发 Ubuntu/Mac OSX。为了能够跨平台处理窗口创建,我使用了 SFML 库 (2.0)。

这里是简化的CApp类及相关函数:

class CApp
{
public:
    //! Constructor.
    CApp(void);
    //! Deconstructor.
    ~CApp(void);

    /* Public Functions: */
    //! Initializer function, needs to be called before Run-Function to allocate everything and set everything up.
    bool Initialize(unsigned int width, unsigned int height, char* title, bool vsync, CState* startState);
    void Run(void); //!< Starts the game-loop
private:
    void ProcessEvent(sf::Event event);

    sf::RenderWindow*   m_pWindow;      //!< window instance
    std::vector<std::thread> m_threads;
};

一般来说,我的应用程序是一个小型 OpenGL 演示场景,它应该是多线程的,以便能够对多线程适合和不适合的地方进行基准测试和比较。

相关函数的实现:

void CApp::Run(void)
{
    while (m_pWindow->IsOpen())
    {
        sf::Event event;
        while (m_pWindow->PollEvent(event))
        {
            m_threads.push_back(std::thread(&CApp::ProcessEvent, this, event)); 
        } 
        // ...
        m_threads.clear();
    }
}

void CApp::ProcessEvent(sf::Event event)
{
    if (event.Type == sf::Event::Closed)
        m_pWindow->Close();
    if (event.Type == sf::Event::KeyPressed) 
    {
        if (event.Key.Code == sf::Keyboard::Escape)
            m_pWindow->Close();
    }
}

我得到的运行时错误只是一个 Abort 陷阱:第一帧上的 6: _"终止调用而没有活动异常 - 程序收到信号 SIGABRT,已中止。 0x00007fff8fdf4ce2 in __pthread_kill()"_

如果我注释掉线程创建,只在当前线程中调用ProcessEvent,没有问题,所以问题一定是线程相关的。

SFML 并不是所有线程安全的,所以我认为问题出在 m_pWindow-Pointer 或作为函数参数本身的事件,但我该如何解决这个问题?

【问题讨论】:

  • 确实非常努力地尝试不要不断地创建、终止和销毁线程。这样的设计,err..'不是最优的',由于开销和容易出错和锁定。对这样的设计进行基准测试具有误导性。

标签: c++ multithreading c++11 sfml


【解决方案1】:

在清除向量并删除所有线程之前,您绝对应该等待所有线程完成:

void CApp::Run(void)
{
    while (m_pWindow->IsOpen())
    {
        sf::Event event;
        while (m_pWindow->PollEvent(event))
        {
            m_threads.push_back(std::thread(&CApp::ProcessEvent, this, event)); 
        } 

    for(auto& i : m_threads)
      i.join();

    m_threads.clear();
   }
}

此外,当您使用 GCC 时,我建议您使用 -pthread 选项进行编译。

【讨论】:

    猜你喜欢
    • 2019-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-16
    • 2011-01-23
    • 1970-01-01
    相关资源
    最近更新 更多