Issue with Qt thread affinity and moveToThread

后端 未结 4 1833
长发绾君心
长发绾君心 2021-01-13 07:58

I\'m trying to use threads in Qt to delegate some work to a thread, but I can\'t get it to work. I have a class inheriting QMainWindow that have a member object that launch

相关标签:
4条回答
  • 2021-01-13 08:32

    I think the problem is with the initialization of m_poller, which according to the error message seems to be assigned to a different (third) thread from the one that is executing your code snippet.

    Also, if this code is executed multiple times, it may work the first time but then fail on subsequent times as m_poller no longer belongs to the executing thread, but rather m_pollThread.

    0 讨论(0)
  • 2021-01-13 08:38

    You can only use moveToThread in case when

    • Your object has no parent (because otherwise the parent will have different thread affinity)
    • You are on the object's owner thread so you actually 'push' the object from current thread to another

    So your error message says you're violating the second case. You should call moveToThread from the thread that created the object.
    And according to you

    This object has the QMainwindow as parent.

    So moveToThread will not work, again. You should remove the parent from m_poller object

    0 讨论(0)
  • 2021-01-13 08:39

    You can also move it to your thread by doing it from the object's owner thread.

    #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);
    }
    

    You just need to call

    moveToThread( m_poller, m_pollThread);
    
    0 讨论(0)
  • 2021-01-13 08:47

    If you are moving your object through signals and slots (you have created your m_poller in one thread and called a signal and passed it to a slot of another object which is not in caller thread) make sure to use Qt::DirectConnection type for your connect. In this way your slot will execute in the caller thread and calling moveToThread is in the caller thread.

    0 讨论(0)
提交回复
热议问题