我對Qt/QtQuick相當陌生,我必須開發一個應用程序,它使用一些傳感器數據,這些數據通過網絡在不同線程中定期接收。這些數據應該在C++中用於計算,最新的數據也應該用QML顯示。通過使用互斥體進行保護,數據在QML中可見地更新,所有東西都設置爲在C++內部是線程安全的。 但是,我對QML方面的線程安全性有一些擔憂,我無法在Web上找到關於此主題的信息或示例。具體來說,我關心的是返回一個指針(這是將C++對象返回給QML的唯一方法),而不是一個值,因此也是對象的一個副本。下面是一個證明問題的最小示例:將C++指針返回到在不同線程中更新的QML
// File data.h
#include <QObject>
class Data : public QObject {
Q_OBJECT
Q_PROPERTY(QString someData READ someData WRITE setSomeData NOTIFY someDataChanged)
public:
explicit Data(QObject* parent = nullptr)
:QObject(parent)
{
}
QString someData() const {
return _someData;
}
void setSomeData(const QString& value) {
if (_someData != value) {
_someData = value;
emit someDataChanged();
}
}
signals:
void someDataChanged();
private:
QString _someData;
}; // Data
// File: controller.h
#include <QObject>
#include <thread>
class Controller : public QObject {
Q_OBJECT
Q_PROPERTY(Data data READ data NOTIFY dataChanged)
public:
explicit Controller(QObject* parent = nullptr)
:QObject(parent)
,_running(false)
,_data(nullptr)
{
_data = new Data();
}
virtual ~Controller() {
delete _data;
}
void start() {
_running = true;
_thread = std::thread([this]() { _threadFunc(); });
}
void stop() {
_running = false;
if (_thread.joinable()) {
_thread.join();
}
}
Data* data() {
return _data;
}
signals:
void dataChanged();
private:
void _threadFunc() {
while (_running) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
_data.setSomeData("foo");
emit dataChanged();
}
}
bool _running;
std::thread _thread;
Data* _data;
}; // Controller
// File main.qml
import QtQuick 2.0
Rectangle {
width: 100
height: 100
Text {
anchors.centerIn: parent
text: Controller.data.someData
}
}
數據是一個容納QString屬性的簡單容器。控制器包含屬性數據並啓動一個線程,該線程定期更新數據併發出變化信號。輸出將正確顯示,但返回原始指針感覺非常不安全。所以在這裏我的問題是:
- 如果數據寫入速度過快,當QML使用指針來更新視覺線程同時操縱數據會發生什麼?
- 是否有其他方法可以返回原始指針,例如Qt爲此目的提供的東西以及我還沒有找到的東西?
- 在使用Qt/QML時,我的思維錯誤嗎?我首先開發了C++後端(沒有任何Qt部分),現在我試圖將它連接到GUI。也許我應該從開始分別設計Qt或QML友好的後端?