2

我试图了解信号/插槽如何在 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()返回之前完成工作。所以在发出run_click()时仍然会运行。task_finished(int)finished_result(int)立即开始还是等待run_click()完成?将finished_result(int)在同一个线程中开始run_click()还是在新线程中开始?

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

4

2 回答 2

3

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

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

这称为“排队连接”,是跨不同线程使用信号和插槽时的默认行为。查看文档中的Threads 和 QObjects以获取更多信息,特别是Signals and Slots Across Threads部分。

于 2013-08-29T05:28:14.327 回答
1

鲍里斯的好回答(+1)

我只想为您的第二个问题添加,您希望在不等待 run_click() 的情况下处理finished_result(),那么如果您希望它“安全”运行,则需要将其放入另一个线程(并将其全部连接起来) .

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

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

于 2013-08-29T06:57:46.883 回答