我试图在一个单独的线程上进行一些繁重的计算,所以我不会冻结UI。为此,我使用的是Qt 5.5。
我试图从官方网站实现工作线程example,但不幸的是没有取得多大成功。您可以在下面看到我的代码:
main.cpp中:
int main(int argc, char* argv[]) {
QApplication app(argc, argv);
DepthMap* depthmap = new DepthMap();
DepthMapGrabber* grabber = new DepthMapGrabber(depthmap);
PointCloudWindow myPointCloudWindow;
myPointCloudWindow.setDepthMap(grabber);
myPointCloudWindow.show();
ProcessorController* controller = new ProcessorController(depthmap);
controller->startThread();
return app.exec();
}
ProcessController.h:
class ProcessorController : public QObject
{
Q_OBJECT
// functions
private:
QThread workerThread;
public:
ProcessorController(const DepthMap* depthmap);
~ProcessorController();
void startThread();
public slots:
void handleResults(const QString &);
signals:
void operate(const QString &);
// variables
private:
Processor* m_processor;
};
ProcessController.cpp:
ProcessorController::ProcessorController(const DepthMap* depthmap) {
m_processor = new Processor(depthmap);
}
ProcessorController::~ProcessorController() {
if (m_processor != nullptr) {
delete m_processor;
m_processor = nullptr;
}
workerThread.quit();
workerThread.wait();
}
void ProcessorController::startThread() {
m_processor->moveToThread(&workerThread);
connect(&workerThread, &QThread::finished, m_processor, &QObject::deleteLater);
connect(this, &ProcessorController::operate, m_processor, &Processor::doWork);
connect(m_processor, &Processor::resultReady, this, &ProcessorController::handleResults);
workerThread.start();
// LOG
std::cout << "Worker thread has been started!" << std::endl;
}
void ProcessorController::handleResults(const QString &) {
// LOG
std::cout << "Worker thread finished!" << std::endl;
}
Processor.h:
class Processor : public QObject
{
Q_OBJECT
// functions
public:
Processor(const DepthMap* depthmap);
public slots:
void doWork(const QString ¶meter);
signals:
void resultReady(const QString &result);
// variables
private:
QMutex m_mutex;
const DepthMap* m_depthmap;
};
Processor.cpp:
Processor::Processor(const DepthMap* depthmap) : m_depthmap(depthmap) {}
void Processor::doWork(const QString ¶meter) {
// LOG
std::cout << "Worker thread is working..." << std::endl;
QString result;
// copy cloud and work on the copy
PointCloudPtr myCloud;
m_mutex.lock();
pcl::copyPointCloud(*m_depthmap->cloud, *myCloud);
m_mutex.unlock();
/* ... here is the expensive or blocking operation ... */
emit resultReady(result);
}
问题是,来自处理器的 doWork 永远不会被调用。我究竟做错了什么?提前感谢您的任何解释和帮助!
编辑:
如果我把
QString result;
emit operate(result);
后
workerThread.start();
在 startThread()中,线程被执行!
任何人都可以解释一下这背后的机制是什么?
答案 0 :(得分:1)
很长一段时间,Qt在我们能够操作的线程上提供虚拟任务对象。这是通过QObject :: moveToThread实现的,并且QObject派生的对象必须具有从中启动作业的槽。在这种情况下,插槽是doWork,并且连接到信号操作。
connect(this, &ProcessorController::operate, m_processor, &Processor::doWork);
这就是原因:
emit operate(desiredStr);
应该解决问题。
顺便说一句。如果不需要用户定义信号的特定推送,我们总是可以使用QThread :: started信号。在这种情况下,doWork插槽不会接收参数。
connect(&workerThread, &QThread::started, m_processor, &Processor::doWorkNoParams);