代码之家  ›  专栏  ›  技术社区  ›  Mark

Qt6多线程问题

  •  0
  • Mark  · 技术社区  · 3 年前

    我在看书 this this 博士。

    基本上我有这个功能:

    bool Flow::checkNfc()
    {
        QByteArray id;
        QByteArray data;
    
        bool ret = _nfc.read(&id, &data, 8);
        if (ret)
        {
            // do something
        }
    
        return ret;
    }
    

    bool ret = _nfc.read(&id, &data, 8);
    

    轮流打电话 libnfc 阻止当前线程的函数。

    因为两者 checkNfc _nfc.read 函数需要与主线程交换数据,我不确定是否可以使用 QFutureWatcher 方法我试过这样的方法:

    QFutureWatcher<bool> watcher;
    QFuture<bool> future = QtConcurrent::run(&MyProject::checkNfc);
    watcher.setFuture(bool);
    

    所以我想试试这个 QThread 解决方案问题在于,对于真实案例场景来说,示例过于简单:

    class Worker : public QObject
    {
        Q_OBJECT
    
    public slots:
        void doWork(const QString &parameter) {
            QString result;
            /* ... here is the expensive or blocking operation ... */
            emit resultReady(result);
        }
    
    signals:
        void resultReady(const QString &result);
    };
    

    不管怎样,我试过了,在我的主要课堂上,我写道:

    private:
        QThread _nfcThread;
        MyNfc _nfc;
    
    private slots:
        void nfc_readResult(bool success, QByteArray id, QByteArray data);
    

    _nfc.moveToThread(&_nfcThread);
    connect(&_nfcThread, &QThread::finished, &_nfc, &QObject::deleteLater);
    connect(&_nfc, &MyNfc::resultRead, this, &MyProject::nfc_readResult);
    _nfcThread.start();
    

    并从计时器插槽:

    _nfc.doWork();
    

    在MyNfc中:

    signals:
        void resultRead(bool result, QByteArray id, QByteArray data);
    
    public slots:
        void doWork();
    

    void MyNfc::doWork()
    {
        QByteArray id;
        QByteArray data;
    
        bool ret = read(&id, &data, 8);
        emit resultRead(ret, id, data);
    }
    

    一切都还在继续。。。但我的主应用程序仍然会在每次调用时阻塞 doWork() .

    我错过了什么?

    1 回复  |  直到 3 年前
        1
  •  1
  •   HiFile.app - best file manager    3 年前

    你不能打电话 doWork()

    因此,触发辅助线程执行工作的正确方法是以下连接:

    connect(&_nfcThread, &QThread::started, &_nfc, &MyNfc::doWork);
    

    嫁妆 .

    deleteLater() deleteLater()

    _nfc.moveToThread(&_nfcThread);
    connect(&_nfcThread, &QThread::started, &_nfc, &MyNfc::doWork); // this starts the worker
    connect(&_nfc, &MyNfc::resultRead, this, &MyProject::nfc_readResult); // this passes the result
    connect(&_nfc, &MyNfc::resultRead, &_nfcThread, &QThread::quit); // this will quit the event loop in the thread
    _nfcThread.start();
    

    更新:如果要定期调用插槽,请连接计时器。当工作完成时,不要退出线程。最简单的情况是:

    _nfc.moveToThread(&_nfcThread);
    connect(&_nfcThread, &QThread::started, &_timer, &QTimer::start); // this starts the timer after the thread is ready
    connect(&_timer, &QTimer::timeout, &_nfc, &MyNfc::doWork); // start work at timer ticks
    connect(&_nfc, &MyNfc::resultRead, this, &MyProject::nfc_readResult); // this passes the result
    _nfcThread.start();
    

    但是,由于没有退出事件循环,因此需要在删除线程之前手动退出它。最好的位置是在主类的析构函数中。

    MainClass::~MainClass()
    {
      _nfcThread.quit(); // this schedules quitting of the event loop when the thread gets its current work done
      _nfcThread.wait(); // this waits for it, this is important! you cannot delete a thread while it is working on something.
      // ... because the thread (and the worker too) will get deleted immediately once this destructor body finishes, which is... right now!
    }
    

    推荐文章