我试图通过构建一个应用程序来与线扫描相机交谈。unsigned short
最终,我想每 100 毫秒从一个QThread
(数据采集)到一个QRunnable
(数据处理)传递一个 384x128 值的“块”(即数组)。这意味着QRunnable
在下一个块到达之前将有 100 毫秒的时间来处理数据。
我仍然不确定移动数据的正确方法。现在,我正在使用 QVector。在 Qt4 中,我理解隐式共享意味着如果在信号中发出 QVector,则不会复制 QVector,直到对象被写入。但是,在我制作的一个小型测试应用程序中,我不确定我是否完全理解这意味着什么。这是下面提供的 MWE 的输出...
Acquire thread: init.
Acquire thread: block acquired: 0x106485e78 Content: {1, 2, 3, 4}
GUI thread: received signal: 0x7fff5fbfda98 Content: {1, 2, 3, 4}
Acquire thread: block acquired: 0x106485e78 Content: {1, 2, 3, 4}
GUI thread: received signal: 0x7fff5fbfda98 Content: {1, 2, 3, 4}
Acquire thread: block acquired: 0x106485e78 Content: {1, 2, 3, 4}
GUI thread: received signal: 0x7fff5fbfda98 Content: {1, 2, 3, 4}
我正在使用具有四个值的“虚拟”QVector,并在线程运行时跟踪向量的地址。数据自始至终都是正确的,但似乎复制了一份。我不会在应用程序的任何时候更改数据......只是显示。我一直在尝试使用const QVector<unsigned short>
,使用引用的各种迭代等。地址总是在变化。由于性能在这里很重要,所以我担心在 384*128 值时制作 QVector 的副本。
另外,在另一个 SO 问题中,我正在努力弄清楚如何让 QRunnable 接收数据(本示例中都省略了)。但是,这里要注意这一点很重要,因为我的想法是让 QRunnable 对存在于 QThread 中的引用进行操作。image_buffer
我只是还没想好怎么做。
具体问题:
-- 为什么看起来是复制品?这是因为多线程吗?
-- 我是否必须在整个过程中明确使用引用(即 image_buffer&),从而完全删除 QVector?或者,我应该担心副本吗?
- 对于我的情况,将数据从 QThread 传递到 QRunnable 的正确方法是什么?
MWE 下面来演示不同的地址。免责声明:我正在学习 C++。没有经过正规培训,只是摆在我面前的几本好书。
主文件
#include <QApplication>
#include <QMetaType>
#include <QVector>
#include "appwidget.h"
int main(int argc, char* argv[]) {
QApplication app(argc, argv);
AppWidget gui;
gui.show();
qRegisterMetaType<QVector<unsigned short> >("QVector<unsigned short>");
return app.exec();
}
** appwidget.h **
#ifndef APPWIDGET_H
#define APPWIDGET_H
#include <QWidget>
#include <QVector>
#include "acquire.h"
class AppWidget : public QWidget
{ Q_OBJECT
public:
AppWidget(QWidget *parent = 0);
protected:
Acquire thread;
public slots:
void processBlock(QVector<unsigned short>);
};
#endif
应用小部件.cpp
#include <QtGui>
#include <iostream>
#include "appwidget.h"
AppWidget::AppWidget(QWidget *parent)
: QWidget(parent)
{
thread.liftoff();
connect(&thread, SIGNAL(blockAcquired(QVector<unsigned short>)), this, SLOT(processBlock(QVector<unsigned short>)));
setWindowTitle(tr("TestApp"));
resize(550, 400);
}
void AppWidget::processBlock(QVector<unsigned short> display_buffer)
{
std::cout << "GUI thread: received signal: "
<< &display_buffer
<< " Content: {"
<< display_buffer.at(0) << ", "
<< display_buffer.at(1) << ", "
<< display_buffer.at(2) << ", "
<< display_buffer.at(3)
<< "}" << std::endl;
}
获取.h
#ifndef ACQUIRE_H
#define ACQUIRE_H
#include <QVector>
#include <QThread>
class Acquire : public QThread {
Q_OBJECT
public:
Acquire(QObject *parent = 0);
~Acquire();
QVector<unsigned short> display_buffer;
void liftoff();
signals:
void blockAcquired(QVector<unsigned short>);
protected:
void run();
private:
};
#endif
获取.cpp
#include <iostream>
#include <time.h>
#include <stdlib.h>
#include "acquire.h"
Acquire::Acquire(QObject *parent)
: QThread(parent)
{
}
Acquire::~Acquire()
{
std::cout << "Acquire thread: dying." << std::endl;
wait();
}
void Acquire::liftoff()
{
std::cout << "Acquire thread: init." << std::endl;
start();
}
void Acquire::run()
{
QVector<unsigned short> display_buffer(2 * 2);
forever {
/*
display_buffer will ultimate be a memcpy of image_buffer
.. image_buffer updated continuously, 1 line every 800000ns x 128 lines
*/
display_buffer[0] = 1;
display_buffer[1] = 2;
display_buffer[2] = 3;
display_buffer[3] = 4;
nanosleep((struct timespec[]){{0, 800000*128}}, NULL);
std::cout << "Acquire thread: block acquired: "
<< &display_buffer
<< " Content: {"
<< display_buffer.at(0) << ", "
<< display_buffer.at(1) << ", "
<< display_buffer.at(2) << ", "
<< display_buffer.at(3)
<< "}" << std::endl;
emit blockAcquired(display_buffer);
}
}