c++ qt多线程在主窗口中调用但是没有效果

问题描述 投票:0回答:1
class MyThread : public QObject{
    Q_OBJECT
    void work(){     
        qDebug()<<"MyThread::work() thread id: "<<QThread::currentThreadId()<<"\n"; 
    }
}
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    qDebug()<<"main thread id: "<<QThread::currentThreadId()<<"\n";
    QThread* subThread = new QThread;
    MyThread* my_thread = new MyThread;
    my_thread->moveToThread(thread1);
    my_thread->start(); 
    
    qDebug()<<"00000000";
    my_thread->work();
    
    connect(ui->pushButton, &QPushButton::clicked, my_thread, &MyThread::work);
    connect(ui->pushButton, &QPushButton::clicked, this, [=]{
        qDebug()<<"11111111";
        my_thread->work();
    });
    connect(ui->pushButton, &QPushButton::clicked, my_thread, [=]{
        qDebug()<<"22222222";
        my_thread->work();
    });
}

程序执行结果:

main thread id:  0x1a70 

00000000
MyThread::work1() thread id:  0x1a70 

11111111
MyThread::work1() thread id:  0x1a70 

MyThread::work1() thread id:  0x698 

22222222
MyThread::work1() thread id:  0x698 

请问为什么主窗口直接调用 my_thread->work(),conncet(ui->pushbuton, &QPushButton::clicked, this, [=]{my_thread->work() ;});两者都是在主线程中执行,而另外两个调用在子线程中正确执行?

c++ qt qthread
1个回答
0
投票

将问题中的代码问题放在一边,规则是连接到信号的代码在创建/移动到 receiver 对象(而不是发射器)的线程中执行(至少默认情况下,更多稍后再说)。

除了直接调用

work
方法的一种情况外,所有连接都是通过
Qt::AutoConnection
完成的。引用:

如果接收器位于发出信号的线程中,则使用 Qt::DirectConnection。否则,使用 Qt::QueuedConnection。连接类型在信号发出时确定。

然后:

  1. this
    MainWindow
    )是在主线程中创建的(
    QWidget
    的实例只能在主线程中创建,不能移动),因此:

    1. my_thread->work();
      从主线程调用。
    2. 连接
       connect(ui->pushButton, &QPushButton::clicked, this, [=]{ ... });
      将在主线程中执行lambda。 (由于
      ui->pushButton
      this
      QWidget
      的两个实例都位于同一个线程中,因此它实际上是
      Qt::DirectConnection
  2. my_thread 
    (
    MyThread*
    ) 已在主线程中创建,然后移至工作线程。

    1. connect(ui->pushButton, &QPushButton::clicked, my_thread, &MyThread::work);
      实际上是
      Qt::QueuedConnection
      ,因此
      work
      将从工作线程执行。
    2. connect(ui->pushButton, &QPushButton::clicked, my_thread, [=]{ ...});
      是等价的,即将从工作线程执行。

对于后 2 个连接,您可以使用

work
强制
Qt::DirectConnection
/lambda 从主线程执行。
这种方法很少被推荐,但是是可能的。

最终细节:

  • 使用
    Qt::DirectConnection
    连接的方法/lambda(无论是显式的还是通过
    Qt::AutoConnection
    )都会立即执行,即:在 emitter 的线程中(根据链接文档,又名 signalling thread),并且无需等待返回事件循环。
  • 相比之下,使用
    Qt::QueuedConnection
    连接的方法/lambda 在执行之前会有一些延迟,因为您必须等待事件循环执行。

这就是输出按照您在函数中呈现的方式排序的原因:排队的连接落后于直接连接。
如果一切都是

Qt::DirectConnection
,则事情将以您连接它们的相同顺序执行。

© www.soinside.com 2019 - 2024. All rights reserved.