【问题标题】:How do I process signals in main thread with mutex locked?如何在互斥锁锁定的主线程中处理信号?
【发布时间】:2019-04-05 06:31:35
【问题描述】:

我正在编写一个多线程的 Qt 应用程序,但由于与 OpenGL 相关的调用,部分代码必须始终在主线程中执行。

模拟问题的粗略代码将是:

QMutex mutex;

void openGLCalls()
{
}
void foo1()
{
    mutex.lock();
    openGLCalls();
    mutex.unlock();

}

class CBHandler : public QObject
{

public:
    CBHandler(QObject *parent = NULL)
    {
        connect(this, SIGNAL(requestCallbackExec()), SLOT(runCallback()),    Qt::BlockingQueuedConnection);

    }

    static CBHandler *Instance();

    public slots:

    void runCallback  ()
    {
        //in the main thread as object lies there
        openGLCalls();
    }

signals:
    void requestCallbackExec ();

};

class Thread1
{
    void run()
    {
        while(1)
        {
            mutex.lock();
            CBHandler::Instance()->emit requestCallbackExec();
            mutex.unlock();
        }
    }
};

void main()
{

    Thread1 thread;
    CBHandler cbhandler;
    thread.start();
    while(1)
    {
        if(/*some key pressed*/)
        {
            foo1();
        }
    }
}

以上代码确保“openGLCalls()”始终在主线程中执行。 但问题是,如果互斥锁被 Thread1 锁定并且主线程尝试调用 foo1,那么主线程在尝试锁定互斥锁时会休眠。 由于主线程处于休眠状态,因此被 Thread1 锁定的互斥体永远不会被解锁,因为“requestCallbackExec”信号永远不会得到处理。

【问题讨论】:

  • 你的互斥锁到底保护的是什么?
  • '//做点什么'。 mutex 确保 //do 某事由主线程或工作线程执行
  • 我用'openGLCalls()'替换了//do something,但它不完全是一个函数。主线程可能会做一些可以改变数据的事情,而工作线程可能想通过其他代码来读取。
  • 这不计算。工作线程 (1) 请求启动回调并 (2) 读取共享数据。第二件事需要由互斥锁保护。但是你为什么要保护第一个呢?
  • 你的 foo1() 可以 tryLock() 互斥体并在失败时返回

标签: c++ multithreading qt c++11 mutex


【解决方案1】:

您应该在.lock() 等待时让事件循环旋转。似乎没有办法做到这一点。所以你可以忙着等待:

while(!mutex.tryLock()) {
    QEventLoop loop;
    loop.processEvents();
}

您可以在 .tryLock() 调用中添加超时以不加热 CPU,但这会花费您一些延迟。

【讨论】:

  • 这解决了问题,但由于我是stackoverflow的新手,所以我的投票不算数。
  • 但是我自己找到了更好的解决方案。如果其他人有兴趣,我使用 QWaitCondition 和 QCoreApplication::postEvent()。当然接收者和事件必须是你自己定义的,这样你才能调用'QWaitCondition::wakeOne()'
猜你喜欢
  • 2020-07-03
  • 2012-12-25
  • 2013-01-31
  • 2021-12-12
  • 2012-05-07
  • 1970-01-01
  • 2021-02-19
  • 2023-03-09
  • 1970-01-01
相关资源
最近更新 更多