未调用 Qt moveToThread 插槽

Posted

技术标签:

【中文标题】未调用 Qt moveToThread 插槽【英文标题】:Qt moveToThread slot not called 【发布时间】:2014-08-14 12:24:54 【问题描述】:

我有一堂课Manager

class Manager : public QThread 

    Q_OBJECT
    public:
    Manager();
    void run()
    
        taskB = new TaskB();
        taskA = new TaskA();
        connect(taskA, SIGNAL(signalOk()), taskB, SLOT(onSignalOk()));
        connect(taskA, SIGNAL(moveOk()), taskB, SLOT(onMoveOk()));
        connect(taskB, SIGNAL(signal()), taskA, SLOT(onSignal()));
        connect(taskB, SIGNAL(moveToThreadSignal(QThread*)), taskA, SLOT(onMoveToThread(QThread*)));
        connect(this, SIGNAL(runSignal()), taskB, SLOT(onRun()));
        emit runSignal();
    
    TaskA* taskA;
    TaskB * taskB;
    signals:
    void runSignal();
    ;

我也有这样的课程TaskA

class TaskA : public QObject

    Q_OBJECT
    public:
    TaskA();
    void run()
    
        std::cout << "[INFO] : Task run: " << QThread::currentThreadId() << std::endl;
        emit signalOk();
    
    public slots:
    void onSignal()
    
        run();
    
    void onMoveToThread(QThread * t)
    
        std::cout << "[INFO] : Task A after move to thread: " << QThread::currentThreadId() << std::endl;
        this->moveToThread(t);
        std::cout << "[INFO] : Task A after move to thread: " << QThread::currentThreadId() << std::endl;
        emit moveOk();
    
    signals:
    void signalOk();
    void moveOk();
;

我也有这样的课程TaskB

class TaskB : public QObject

    Q_OBJECT
    public:
    TaskB();
    void run()
    
        std::cout << "[INFO] : TaskB run: " << QThread::currentThreadId() << std::endl;
        emit signal();
    
    signals:
    void signal();
    void moveToThreadSignal(QThread* t);
    public slots:
    void onSignalOk()
    
        std::cout << "[INFO] : TaskB onSignalOk : " << QThread::currentThreadId() << std::endl;
    
    void onMoveOk()
    
        std::cout << "[INFO] : TaskB onMoveOk: " << QThread::currentThreadId() << std::endl;
        run();
    
    void onRun()
    
        std::cout << "[INFO] : TaskB emit MoveToThreadSignal: " << QThread::currentThreadId() << std::endl;
        thread = new QThread();
        thread->start();
        emit moveToThreadSignal(thread);
    
    private:
    QThread * thread;
;

当我启动管理器时:

经理 *_manager = 新经理();

_manager->start();

TaskB 的槽 onSignalOk() 未被调用。

我认为问题原因是我连接信号时的默认参数Qt::AutoConnection,但我不明白。

【问题讨论】:

这里还有其他问题,需要考虑线程亲和性。我建议你从阅读这篇文章开始:mayaposch.wordpress.com/2011/11/01/… 这个标题具有误导性。 Qt 中有一个 movetoThread 和一个名为 movetoThreadSignal 的函数。大不同。 让我们退后一步。你最终想做什么?上面的代码有很多缺陷。特别是thread = new QThread();thread-&gt;start();。您对这段代码有什么期望? 这段代码只是一个板凳。我的项目是任务管理器。 TaskB 是并行运行其他任务(如 TaskA)的任务。 感谢@Merlin069 的评论。通过这篇文章,我更正了我的经理,它现在可以工作了。 Manager 继承 QObject 而不是 QThread,然后我使用 moveToThread。 【参考方案1】:

我建议从不继承 QThread 开始;它的名称具有误导性,因为它更像是一个线程管理器。在我看来,从 QThread 继承的唯一原因是如果你想改变 Qt 管理线程的方式。

相反,只需从 QObject 继承并将对象移动到新线程。这样做的好处是能够将多个对象移动到一个新线程,而不是在继承 QThread 时为每个对象创建一个单独的线程。

【讨论】:

以上是关于未调用 Qt moveToThread 插槽的主要内容,如果未能解决你的问题,请参考以下文章

未连接的 Qt 插槽被调用

Qt 插槽未被调用

QT5 插槽未在子类中调用

未调用 Qt 信号槽

PySide (Qt) 信号未到达我的插槽

从 JavaScript 调用 Qt 插槽