如何在锁定互斥锁的情况下处理主线程中的信号

How do I process signals in main thread with mutex locked?

本文关键字:处理 情况下 线程 信号 锁定      更新时间:2023-10-16

我正在编写一个多线程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"信号永远不会被处理。

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

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

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