私は、ラインスキャン カメラと対話するアプリケーションを構築することで、自分の道を歩もうとしています。最終的に、 (データ取得) から(データ処理)に 100 ミリ秒unsigned short
ごとに 384x128 値の「ブロック」(つまり、配列) を渡したいと考えています。これは、次のブロックが到着する前にデータを処理するのに 100 ミリ秒かかることを意味します。QThread
QRunnable
QRunnable
データを移動する正しい方法はまだわかりません。現在、私は QVector を使用しています。Qt4では、オブジェクトが書き込まれるまで、シグナルで発行された場合、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}
4 つの値を持つ「ダミー」の QVector を使用し、スレッドの実行時にベクトルのアドレスを追跡しています。データは全体的に正しいですが、コピーが作成されているようです。アプリケーションのどの時点でもデータを変更していません...表示するだけです。const QVector<unsigned short>
全体を通して、参照などを使用するさまざまな反復を使用してみました。アドレスは常に変更されます。ここではパフォーマンスが重要になるため、384*128 の値の場合に QVector のコピーを作成することに関心があります。
また、別の SO の質問では、QRunnable にデータを受信させる方法を理解するのに苦労しています (この例ではすべて除外されています)。しかし、私の考えは QRunnable が QThread に存在する への参照で動作するようにすることであるため、ここで注意することが重要ですimage_buffer
。私はそれを行う方法を理解していません。
具体的な質問:
-- コピーが作成されたように見えるのはなぜですか? これはマルチスレッドのせいですか?
-- 明示的に参照 (つまり、image_buffer&) を使用して、QVector を完全に削除する必要がありますか? または、コピーについて心配する必要がありますか?
-- 私の状況で QThread から QRunnable にデータを渡す正しい方法は何ですか?
以下の MWE は、さまざまなアドレスを示しています。免責事項: 私は C++ を学んでいます。正式なトレーニングはなく、目の前にいくつかの優れた本があります。
main.cpp
#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
appwidget.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);
}
}