我正在尝试了解信号/插槽如何在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()
完成。任何想法如何进行?我是否需要在新线程中将“更多内容”移动到另一个工作人员?
答案 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”,一旦收到信号就会处理该信号,这是同一线程内信号的默认设置,但是这样做是为了跨线程执行此操作非常危险,所以不要被这个选项诱惑!
可能有第三个选项暂停当前事件并找到事件队列中的下一个项目..但我不确定,我以为我读了这样的事情,但是找不到它。 ..也许有人可以回答那部分? (我来看看能否找到这个)。