怎样在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);
}
伊卡洛斯不落
10 years, 9 months ago
Answers
参考:
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_())
霧雨·潶白
answered 10 years, 9 months ago