Qt线程关联和moveToThread的问题

2024-05-28 20:44:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图使用Qt中的线程来将一些工作委托给线程,但我无法使其工作。我有一个继承QMainWindow的类,该类有一个成员对象,该对象启动线程以执行工作。此对象将QMainwindow作为父对象。它包含并初始化另一个QObject m_poller,我想将其移到我创建的线程中:

m_pollThread = new QThread;
m_poller->moveToThread(m_pollThread);
//Bunch of connection
m_pollThread->start();

我遵循了关于如何在Qt中管理线程而不对其进行子类化(又称not doing it wrong)的指导原则,但在VS中仍然得到以下消息:

QObject::moveToThread: Current thread (0x2dfa40) is not the object's thread (0x120cf5c0). Cannot move to target thread (0x1209b520)

我发现following post似乎处理了相同的问题,但无法用答案修复我的代码。我觉得我实际上正确地调用了moveToThread(因为我没有从另一个线程中调用它来“拉”对象到它),但显然我仍然缺少一些东西:消息提示,似乎已经有多个线程了,而且我对moveToThread()的调用似乎以错误的方式结束(尽管我承认我对这一点还不太熟悉,而且可能会发现这是完全错误的…)

那么我使用Qt线程的方式可能还有什么问题?

谢谢!


Tags: 对象消息错误方式not成员qt线程
3条回答

我认为问题出在m_poller的初始化上,根据错误消息,它似乎被分配给了与执行代码片段的线程不同的(第三个)线程。

此外,如果这段代码被多次执行,它可能会在第一次工作,但随后会失败,因为m_poller不再属于执行线程,而是m_pollThread。

只有在以下情况下才能使用moveToThread

  • 您的对象没有父对象(否则父对象将具有不同的线程关联)
  • 您位于对象的所有者线程上,因此实际上将对象从当前线程“推”到另一个线程

所以你的错误信息说你违反了第二个案子。您应该从创建对象的线程中调用moveToThread
根据你的说法

This object has the QMainwindow as parent.

所以moveToThread不会再工作了。应该从m_poller对象中删除父对象

也可以通过从对象的所有者线程中执行此操作,将其移动到线程中。

#include <thread>
#include <memory>
#include <condition_variable>
#include <QTimer>
#include <QThread>
#include <QApplication>


template <typename Func>
inline void runOnThread(QThread *qThread, Func &&func)
{
    QTimer *t = new QTimer();
    t->moveToThread(qThread);
    t->setSingleShot(true);
    QObject::connect(t, &QTimer::timeout, [=]()
    {
        func();
        t->deleteLater();
    });
    QMetaObject::invokeMethod(t, "start", Qt::QueuedConnection, Q_ARG(int, 0));
}



void moveToThread(QObject *ptr, QThread *targetThrd=QThread::currentThread())
{
    std::mutex mt;
    std::condition_variable_any cv;
    runOnThread(ptr->thread(),[&]
    {
        ptr->setParent(NULL);
        ptr->moveToThread(targetThrd);
        cv.notify_one();
    });
    cv.wait(mt);
}

你只要打个电话

moveToThread( m_poller, m_pollThread);

相关问题 更多 >

    热门问题