検索

ホームページ  >  に質問  >  本文

c++ - 怎样在qt中触发多线程并行运算?

在主线程中向其他n个子线程发送event,让子线程并行运算,运算完成后向主线程发送信号,并等待下一次event到达。而主线程则等待所有子线程运算完成后,再次发送event。

我用postEvent向子线程发送消息,然后调用sendPostedEvent,发现子线程是按照postEvent的先后顺序执行的,并不是并行的运算。

比如有4个calculator线程,其中id 0的运算0秒,id 1的运算1秒,... id 3的运算3秒,就是id越小的运算越早结束, 如果同时计算完成的顺序应该是0,1,2,3。如果按照0 ~ 3的顺序向calculator发送事件,是这个顺序。而按照3 ~ 0的顺序发送,完成的顺序是3,2,1,0. 而不是我想象中的0,1,2,3.

请问,在这种情况下,应该怎样触发多线程的并行运算?谢谢!

代码:
calculator.h

#ifndef CALCULATOR_H
#define CALCULATOR_H

#include <QObject>
#include <QThread>
#include <QEvent>

class Calculator : public QThread
{
    Q_OBJECT
public:
    explicit Calculator(int thread_id, int sleep_interval, QObject *parent = 0)
        : QThread(parent)
        , thread_id_(thread_id)
        , sleep_interval_(sleep_interval)
    {}

    void stop(int /*exit_code*/) {
        QThread::exit();
        sleep(sleep_interval_);
        emit resultReady(thread_id_);
    }

protected:
    void run() Q_DECL_OVERRIDE{
        exec(); //wait for event
    }

    bool event(QEvent */*myevent*/) {
        sleep(sleep_interval_);
        emit cal_finished(thread_id_);  //return thread id
        return true;
    }

signals:
    void cal_finished(int result);
    void resultReady(int result);

private:
    int thread_id_;
    int sleep_interval_;
};


#endif // CALCULATOR_H

DataSender.h

#ifndef DATASENDER_H
#define DATASENDER_H

#include <QCoreApplication>
#include "calculator.h"
#include <iostream>
#define THREAD_NUMBER 4

class DataSender : public QObject
{
    Q_OBJECT
public:
    explicit DataSender(QObject *parent = 0) : QObject(parent) {}

public slots:
    void run() {
        //generate and run 4 calculators thread
        Calculator* calculator[THREAD_NUMBER];
        for (int i = 0; i < THREAD_NUMBER; ++i) {
            calculator[i] = new Calculator(i, i, this);
            connect(calculator[i], &Calculator::resultReady , this, &DataSender::handleResults);
            connect(calculator[i], &Calculator::cal_finished, this, &DataSender::cal_finished);
        }

        //post event to thread 0 ~ 3
        for (int j = 0; j < THREAD_NUMBER; ++j)
            QCoreApplication::postEvent(calculator[j], new QEvent(QEvent::User));
        QCoreApplication::sendPostedEvents();
        sleep(4); //wait 4 seconds

        //post event to thread 3 ~ 0
        for (int j = THREAD_NUMBER - 1; j >= 0; --j)
            QCoreApplication::postEvent(calculator[j], new QEvent(QEvent::User));
        QCoreApplication::sendPostedEvents();
        sleep(4); //wait 4 seconds*/


        for (int i = 0; i < THREAD_NUMBER; ++i)
            delete calculator[i];

        emit signalFinished();
    }

    void cal_finished(int result) {
        std::cout << "Thread #" << result << " done.\n";
    }

    void handleResults(int thread_id) {
        std::cout << "Thread #" << thread_id << "Exit\n";
    }

signals:
    void signalFinished();
};

#endif // DATASENDER_H

main.cpp

#include <QCoreApplication>
#include <QTimer>

#include "calculator.h"
#include "datasender.h"


int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);
    DataSender* dataSender = new DataSender(&app);

    QObject::connect(dataSender, SIGNAL(signalFinished()), &app, SLOT(quit()));
    QTimer::singleShot(0, dataSender, SLOT(run()));

    app.exec();

    delete dataSender;
    return (0);
}
PHPzPHPz2809日前779

全員に返信(2)返信します

  • ringa_lee

    ringa_lee2017-04-17 11:24:40

    参考:http://blog.iceyer.net/archives/how-to-use-qtcore-qthread/
    QThread不是通过继承来使用的,而是一种系统资源。需要配合moveToThread使用,给一段简单的python代码做示范:

    #/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    import sys
    import time
    from PyQt4 import QtCore, QtGui
    
    class Worker(QtCore.QObject):
        def __init__(self, parent = None):
            QtCore.QObject.__init__(self, parent)
    
        def runx(self):
            while True:
                print("Worker is working...")
                time.sleep(5)
    
    class MainView(QtGui.QWidget):
        def __init__(self, parent = None):
            QtGui.QWidget.__init__(self, parent)
    
            self.worker = Worker()
            ###delete 3 line below will make mainview block
            **self.workerThread = QtCore.QThread()
            self.worker.moveToThread(self.workerThread)
            self.workerThread.start()**        
            ###
            self.runsignal = QtCore.SIGNAL("runx(PyQt_PyObject)") 
            self.connect(self.worker, self.runsignal, self.worker.runx)
            self.worker.emit(self.runsignal, self.worker)
    
    
    if "__main__" == __name__:
        app = QtGui.QApplication(sys.argv)
    
        mv = MainView()
        mv.show()
    
        sys.exit(app.exec_())
    

    返事
    0
  • 黄舟

    黄舟2017-04-17 11:24:40

    lz我也遇到了同样的问题,请问你是怎么解决多线程的并行问题的?

    返事
    0
  • キャンセル返事