信号是否会创建新线程?

时间:2013-08-29 05:18:35

标签: c++ qt signals-slots qthread

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

mainwindow.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();
};

mainwindow.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()返回之前完成工作。因此,run_click()将在task_finished(int)发出时仍在运行。 finished_result(int)会立即开始还是等待run_click()完成? finished_result(int)会在run_click()或新线程的同一个线程中启动吗?

我的特殊问题是我在“做更多的东西”中有一个不相关的QWaitCondition,它持有该线程一段时间。我希望finished_result(int)继续进行而不等待run_click()完成。任何想法如何进行?我是否需要在新线程中将“更多内容”移动到另一个工作人员?

2 个答案:

答案 0 :(得分:3)

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

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

这称为“排队连接”,是在不同线程中使用信号和插槽时的默认行为。有关详细信息,请查看文档中的Threads and QObjects,尤其是Signals and Slots Across Threads部分。

答案 1 :(得分:1)

鲍里斯的好答案(+1)

我只想添加你的第二个问题,你希望在不等待run_click()的情况下处理finished_result()然后你需要将它放到另一个线程中(并将它连接起来)如果你想让它运行“安全地”。

您可能会看到Qt确实允许您强制连接为“DirectConnection”,一旦收到信号就会处理该信号,这是同一线程内信号的默认设置,但是这样做是为了跨线程执行此操作非常危险,所以不要被这个选项诱惑!

可能有第三个选项暂停当前事件并找到事件队列中的下一个项目..但我不确定,我以为我读了这样的事情,但是找不到它。 ..也许有人可以回答那部分? (我来看看能否找到这个)。