代码结构如下:
class DeviceManager : public QObject {
public:
DeviceManager() : QObject() {
m_worker = new Worker();
m_workerThread = new QThread(this);
m_worker->moveToThread(m_workerThread);
connect(m_workerThread, &QThread::started, m_worker, &Worker::readDevice);
connect(m_worker, &Worker::dataReady, this, &DeviceManager::processData);
m_workerThread->start();
}
~DeviceManager() {
m_hidWork->breakFlag = false;
m_hidWorkThread->quit();
m_hidWorkThread->wait();
m_hidWorkThread->deleteLater();
}
private:
void processData(QByteArray data) {
qDebug() << "Main thread: " << data.toHex(' ');
}
class Worker;
Worker *m_worker;
QThread *m_workerThread;
};
class DeviceManager::Worker : public QObject {
Q_OBJECT
public:
Worker(QObject *parent = nullptr) : QObject(parent) {}
bool breakFlag = true;
void readDevice() {
auto buffer = new char[1024];
while(breakFlag) {
size_t size = 5;
memset(buffer, 0, size)
// 这里是模拟读取设备数据
buffer = {0x01, 0x02, 0x03, 0x04, 0x05};
QByteArray deviceData = QByteArray::fromRawData(reinterpret_cast<char*>(buffer), size);
qDebug() << "Worker thread: " << deviceData.toHex(' ');
emit dataReady(QByteArray(deviceData));
}
}
signals:
void dataReady(QByteArray data);
};
在运行这段代码时,当主线程进行了一个UI阻塞操作的时候,我们观察会到工作线程和主线程中打印的QByteArray
内容不一致。例如:
Worker thread: 01 02 03 04 05
Main thread: 00 00 00 00 00
这显然不是我们期望的结果,因为两个线程应该打印相同的数据。
经过仔细分析,我们发现问题的根源在于QByteArray::fromRawData()
的使用方式。这个函数创建了一个共享底层数据的QByteArray
,而不是复制数据。这意味着:
fromRawData()
创建的QByteArray
与原始缓冲区共享数据。QByteArray
的内容可能变得无效。解决这个问题的关键是确保在发送信号时创建QByteArray
的完整副本。以下是修改后的Worker::readDevice()
方法:
void Worker::readDevice() {
auto buffer = new char[1024];
while(breakFlag) {
size_t size = 5;
memset(buffer, 0, size)
// 这里是模拟读取设备数据
buffer = {0x01, 0x02, 0x03, 0x04, 0x05};
//QByteArray deviceData = QByteArray::fromRawData(reinterpret_cast<char*>(buffer), size);
QByteArray deviceData((reinterpret_cast<char*>(buffer), size); // 创建数据的副本
qDebug() << "Worker thread: " << deviceData.toHex(' ');
emit dataReady(deviceData);
}
}
这里的改动看似很小,但却解决了问题:
QByteArray(const char *data, int size)
构造函数来创建QByteArray
。QByteArray
对象,其内容不会受到原始缓冲区变化的影响。因篇幅问题不能全部显示,请点此查看更多更全内容