关于QMetaObject::invokeMethod的测试

此函数可以用来在子线程中委托一个线程执行特定函数。QMetaObject::invokeMethod(...)默认在主线程中执行函数,除非指定连接方式为Qt::DirectConnection。但是,如果一个对象使用moveToThread(...)函数将它的槽函数委托到指定的线程执行,那么不管QMetaObject::invokeMethod(...)指定何种连接方式,槽函数都会在指定的线程中执行而不是在调用方所在的线程。以下是测试用的代码和输出结果,在VS2017和Qt5.9上测试通过(注意代码中new obj没有释放)。头文件:

class MCcrt : public QThread
{
    Q_OBJECT

public:
    MCcrt(QObject* parent = 0) : QThread(parent) {}
    ~MCcrt() override = default;

private:
    void run() override;

private slots:
    void func(int a);
};

CPP文件:

void MCcrt::run()
{
    while (1)
    {
        qDebug() << u8"子线程:" << QThread::currentThread();
        QMetaObject::invokeMethod(this, "func", Qt::AutoConnection, Q_ARG(int, 1));
        QMetaObject::invokeMethod(this, "func", Qt::DirectConnection, Q_ARG(int, 2));
        QMetaObject::invokeMethod(this, "func", Qt::QueuedConnection, Q_ARG(int, 3));
        QMetaObject::invokeMethod(this, "func", Qt::BlockingQueuedConnection, Q_ARG(int, 4));
        msleep(10000);
    }
}

void MCcrt::func(int a)
{
    qDebug() << u8"我的线程:" << a << QThread::currentThread();
}

<主窗口构造函数>()
{
    ui.setupUi(this);
    qDebug() << u8"主线程:" << QThread::currentThread();
    MCcrt* obj = new MCcrt;
    obj->start();
}

输出文本为:

主线程: QThread(0x20a8f310140)
子线程: MCcrt(0x20a8f327390)
我的线程: 2 MCcrt(0x20a8f327390)
我的线程: 1 QThread(0x20a8f310140)
我的线程: 3 QThread(0x20a8f310140)
我的线程: 4 QThread(0x20a8f310140)
子线程: MCcrt(0x20a8f327390)
我的线程: 2 MCcrt(0x20a8f327390)
我的线程: 1 QThread(0x20a8f310140)
我的线程: 3 QThread(0x20a8f310140)
我的线程: 4 QThread(0x20a8f310140)

 

posted @ 2023-04-11 14:47  兜尼完  阅读(323)  评论(0编辑  收藏  举报