在QThread的上下文中调用方法

Ida*_*n K 6 c++ qt multithreading qthread

在我的应用程序中有主线程和工作线程(QThread).
从主线程我想调用我的工作线程的方法,让它在线程的上下文中运行.

我已经尝试使用QMetaObject::invokeMethod并给它QueuedConnection选项,但它不起作用.
我也尝试从主线程(连接到工作线程的插槽)发出信号,但也失败了.

这是我尝试的大致的片段:

class Worker : public QThread
{
    Q_OBJECT

public:
    Worker() { }

    void run() 
    { 
        qDebug() << "new thread id " << QThread::currentThreadId(); 
        exec(); 
    }

public slots:
    void doWork()
    {
        qDebug() << "executing thread id - " << QThread::currentThreadId();
    }
};
Run Code Online (Sandbox Code Playgroud)

使用QMetaObject方式:

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qDebug() << "main thread id - " << QThread::currentThreadId();

    Worker worker;
    worker.start();

    QMetaObject::invokeMethod(&worker, "doWork", Qt::QueuedConnection);

    return a.exec();
}
Run Code Online (Sandbox Code Playgroud)

使用信号方式:

class Dummy : public QObject
{
    Q_OBJECT

public:
    Dummy() { }

public slots:
    void askWork() { emit work(); }

signals:
    void work();
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qDebug() << "main thread id - " << QThread::currentThreadId();

    Worker worker;
    worker.start();

    Dummy dummy;
    QObject::connect(&dummy, SIGNAL(work()), &worker, SLOT(doWork()), Qt::QueuedConnection);

    QTimer::singleShot(1000, &dummy, SLOT(askWork()));

    return a.exec();
}
Run Code Online (Sandbox Code Playgroud)

两种方式都会导致主线程ID被打印出来QThread doWork.

此外,我想实现一个简单的生产者 - 消费者,但如果这有效,是否有任何理由不这样做?

Ida*_*n K 3

问题在于接收者(QThread)“存在”于主线程中,因此主线程的事件循环是执行该槽的事件循环。

来自 Qt 的文档:

对于排队连接,当控制返回到对象所属线程的事件循环时,将调用槽。槽在接收者对象所在的线程中执行。

所以到目前为止我找到的解决方案是在线程的 run() 内部创建一个对象并使用它的插槽。这样,接收者的所有者就是线程,然后在线程上下文中调用槽。