Qt文档对QtConcurrent::blockingMap说了以下内容:



QtConcurrent::map的文档在其他方面是相同的。它还返回QFuture<void>而不是void

QFuture的文档具有以下说明:



因此,我期望QtConcurrent::blockingMap(seq, f)QtConcurrent::map(seq, f).waitForFinished()相同。但是,事实并非如此。

#include <QObject>
#include <QtConcurrent>

class Foo : public QObject {
Q_OBJECT
public:
    explicit Foo(QObject *parent = nullptr) : QObject(parent) {
        connect(this, &Foo::signal, this, &Foo::slot, Qt::AutoConnection);
    }

    void startMapWithWaiting() {
        qDebug("startMapWithWaiting");
        slot_counter = 0;
        std::atomic_int signal_counter = 0;
        QtConcurrent::map(nums, [&](auto &&num) {
            ++signal_counter;
            emit signal();
        }).waitForFinished();
        qDebug("result: %d signals, %d slots", int(signal_counter), int(slot_counter));
        slot_counter = 0;
    }

    void startBlockingMap() {
        qDebug("startBlockingMap");
        slot_counter = 0;
        std::atomic_int signal_counter = 0;
        QtConcurrent::blockingMap(nums, [&](auto &&num) {
            ++signal_counter;
            emit signal();
        });
        qDebug("result: %d signals, %d slots", int(signal_counter), int(slot_counter));
        slot_counter = 0;
    }

public slots:
    void slot() { ++slot_counter; }

signals:

    void signal();

private:
    std::atomic_int slot_counter = 0;
    std::vector<int> nums{1, 2, 5, 8};
};

#include "main.moc"

int main(int argc, char *argv[]) {
    QCoreApplication app(argc, argv);
    Foo *foo = new Foo(&app);
    QTimer::singleShot(10, foo, [foo, &app]() {
        foo->startMapWithWaiting();
        foo->startBlockingMap();
        app.quit();
    });
    return app.exec();
}

输出为
startMapWithWaiting
result: 4 signals, 4 slots
startBlockingMap
result: 4 signals, x slots
x在0到4之间变化,具体取决于…某物。这令人困惑。

我想知道这两种方式之间有什么区别,以及我如何误读文档。

最佳答案

两种方法的工作方式相同:所有lambda函数均以发出的4个信号终止。在示例中调用的插槽的不同取决于emit signal()的工作方式。由于该程序将Qt::AutoConnection用于信号/插槽:

  • 如果目标线程(创建Foo的主线程)与当前线程(池线程,由全局ThreadPool控制)不同,则将事件放入事件队列,否则,将执行插槽直接(与Qt::DirectConnection相同)。

  • 使用所示的相同示例可以得到不同的结果(x个插槽)。这取决于全局线程池如何管理其线程。在我的配置中,输出为:
        startMapWithWaiting
        result : 4 signals, 0 slots
        startBlockingMap
        result : 4 signals, 4 slots
    

    为了获得相同的结果,我们可以在打印结果之前使用Qt::DirectConnection而不是Qt::AutoConnection或调整QApplication::processEvent():
        QApplication::processEvents(); //<-- force slot() to be processed.
        qDebug("result blocking : %d signals, %d slots", int(signal_counter), int(slot_counter));
    

    关于c++ - QtConcurrent::blockingMap与QtConcurrent::map和waitForFinished,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53978796/

    10-09 13:25