当Qt Slot存在于通过std :: async

时间:2017-10-09 11:58:05

标签: c++ multithreading qt signals-slots

我想创建一个Qt小部件,它通过信号/插槽系统与不同线程上的其他类进行通信。接收对象是在通过std :: async运行的Function中创建的。 问题是:如果小部件发出信号,则不会调用另一个线程上的插槽。

我的例子:

我创建了类MainWindow,它派生自QMainWindow并将存在于主线程上。类接收器是在一个通过std :: async调用的函数中创建的,并且有一个应该在控制台上打印的线程。

我测试了是否通过将信号连接到同一线程上的另一个插槽来发出信号。

MainWindow.hpp

#pragma once

#include <QMainWindow>

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
     explicit MainWindow(QWidget *parent = 0);

signals:
    void send();

private slots:
    void buttonClicked();
    void recieve();
};

MainWindow.cpp

#include "MainWindow.hpp"
#include <iostream>

#include <QPushButton>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent)
{
    QPushButton* start = new QPushButton("Start");
    setCentralWidget(start);
    start->show();

    connect(start, SIGNAL(clicked(bool)), this, SLOT(buttonClicked()));
    connect(this, SIGNAL(send()), this, SLOT(recieve()));
}

void MainWindow::buttonClicked()
{
    std::cout << "MainWindow::buttonClicked()\n";
    emit send();
}

void MainWindow::recieve()
{
    std::cout << "MainWindow::recieve()\n";
}

Reciever.hpp

#include <QObject>

class Reciever : public QObject
{
    Q_OBJECT
public:
    Reciever(QObject *parent = 0);

public slots:
    void recieve();
};

Reciever.cpp

#include "Reciever.hpp"

#include <iostream>

Reciever::Reciever(QObject *parent) : QObject(parent)
{
    std::cout << "Reciever()" << std::endl;
}

void Reciever::recieve()
{
    std::cout << "Reciever::recieve()" << std::endl;
}

的main.cpp

#include "MainWindow.hpp"
#include "Reciever.hpp"
#include <QApplication>

#include <future>

void StartAndConnect(MainWindow &widget)
{
    Reciever* rec = new Reciever();

    QObject::connect(&widget, SIGNAL(send()), rec, SLOT(recieve()));
}

int main(int argc, char *argv[])
{

    QApplication app(argc, argv);

    MainWindow myWidget;

    myWidget.show();

    auto future = std::async(std::launch::async, [&myWidget](){
        StartAndConnect(myWidget);
    });

    app.exec();

    future.wait();
}

经过一些研究后,我最强烈的猜测是,由std :: async启动的线程没有Qt事件循环,因此不会达到处理发布事件(emit)的程度。我更改了主要使用QtConcurrent :: run但它也没有用。

修改

在这里尝试使用QtConcurrent:

main2.cpp

#include "MainWindow.hpp"
#include "Reciever.hpp"
#include <QApplication>

#include <future>
#include <QtConcurrent>

void StartAndConnect(MainWindow &widget)
{
    Reciever* rec = new Reciever();

    QObject::connect(&widget, SIGNAL(send()), rec, SLOT(recieve()));
}

int main(int argc, char *argv[])
{

    QApplication app(argc, argv);

    MainWindow myWidget;

    myWidget.show();

    auto future = QtConcurrent::run( [&myWidget](){
    StartAndConnect(myWidget);
    });

    app.exec();

    future.waitForFinished();
}

1 个答案:

答案 0 :(得分:1)

如果要处理跨线程插槽调用,则需要在线程中运行事件循环。

auto future = QtConcurrent::run( [&myWidget](){
StartAndConnect(myWidget);
QEventLoop e;
e.exec();
});

但我建议使用QThread,因为在你的情况下很明显。 Qt有一个very good documentation,用来描述你的情况。