Do信号创建新线程

Do signals create new threads?

本文关键字:线程 新线程 信号 创建 Do      更新时间:2023-10-16

我正在努力了解信号/插槽在GUI程序中是如何工作的。例如,如果主程序中的一个插槽收到信号,它是否会创建另一个线程来处理该插槽?

主窗口.h

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
public slots:
    void finished_result(int);
private:
    Ui::MainWindow *ui;
    QThread* thread;
    Worker* worker;
private slots:
    void run_click();
};

主窗口.cpp

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),ui(new Ui::MainWindow){
    ui->setupUi(this);
}
MainWindow::~MainWindow(){
    delete ui;
}
void MainWindow::run_click(){
    thread = new QThread;
    Worker* worker = new Worker();
    worker->moveToThread(thread);
    connect(worker,SIGNAL(task_finished(int)),this,SLOT(finished_result(int)));
    // all other necessary signal/slot connections
    thread->start();
    // do more stuff
}
void MainWindow::finished_result(int x){
    // do some stuff
}

在这样的程序中,说"做更多的事情"需要一段时间来处理,工人在run_click()返回之前完成工作。因此,当task_finished(int)发出时,run_click()仍将运行。finished_result(int)会立即启动还是等待run_click()完成?finished_result(int)是在与run_click()相同的线程中启动,还是在新线程中启动?

我的特殊问题是,在我的"做更多的事情"中有一个不相关的QWaitCondition,它会占用该线程一段时间。我希望我的finished_result(int)继续进行,而不必等待run_click()完成。有什么想法可以继续吗?我是否需要将"做更多的事情"转移到新线程中的另一个工作者?

不,信号永远不会创建新线程。

在您的情况下,run_click()finished_result(int x)将在同一线程中按此顺序执行。当信号task_finished(int)从工作线程发出时,它将被传输并在主线程的队列中等待,等待run_click()完成,从而返回事件循环。只有到那时才会调用finished_result(int x)

这被称为"排队连接",是在不同线程中使用信号和插槽时的默认行为。请查看文档中的线程和QObjects以获取更多信息,特别是跨线程的信号和插槽部分。

Boris(+1)的好答案

我只想补充一下你的第二个问题,你希望在不等待run_click()的情况下处理finished_result(),那么如果你希望它"安全"运行,你需要将其放入另一个线程(并将其全部连接起来)。

你可能读到Qt确实允许你强制连接为"DirectConnection",在那里信号一收到就被处理,这是同一线程内信号的默认设置,但跨线程这样做是非常危险的,所以不要被这个选项所诱惑!

可能还有第三个选项可以暂停当前事件并在事件队列中查找下一个项目。。但我不确定,我想我以前读过这样的东西,但找不到…也许有人能回答这个部分?(我会看一看是否能找到这个)。