【发布时间】:2016-04-06 22:30:27
【问题描述】:
我正在使用 Qt 5.2.1 来实现一个程序,该程序从文件中读取数据(可能是几个字节到几 GB)并以依赖于每个字节的方式可视化该数据。我这里的例子是一个十六进制查看器。
一个对象进行读取,并在读取新数据块时发出信号dataRead()。该信号带有一个指向QByteArray 的指针,如下所示:
filereader.cpp
void FileReader::startReading()
{
/* Object state code here... */
{
QFile inFile(fileName);
if (!inFile.open(QIODevice::ReadOnly))
{
changeState(STARTED, State(ERROR, QString()));
return;
}
while(!inFile.atEnd())
{
QByteArray *qa = new QByteArray(inFile.read(DATA_SIZE));
qDebug() << "emitting dataRead()";
emit dataRead(qa);
}
}
/* Emit EOF signal */
}
查看器的loadData 插槽连接到此信号,这是显示数据的函数:
hexviewer.cpp
void HexViewer::loadData(QByteArray *data)
{
QString hexString = data->toHex();
for (int i = 0; i < hexString.length(); i+=2)
{
_ui->hexTextView->insertPlainText(hexString.at(i));
_ui->hexTextView->insertPlainText(hexString.at(i+1));
_ui->hexTextView->insertPlainText(" ");
}
delete data;
}
第一个问题是,如果按原样运行,GUI 线程将完全没有响应。所有的dataRead() 信号都将在重新绘制 GUI 之前发出。
(full code 可以运行,当您使用大于约 1kB 的文件时,您会看到此行为。)
通过对我的论坛帖子 Non-blocking local file IO in Qt5 的回复以及对另一个 Stack Overflow 问题 How to do async file io in qt? 的回答,答案是:使用线程。但是这些答案都没有详细说明如何对数据本身进行洗牌,以及如何避免常见的错误和陷阱。
如果数据很小(大约一百字节),我会用信号发出它。但是如果文件大小为 GB(edit)或者如果文件位于基于网络的文件系统上,例如。 NFS、Samba 共享,我不希望 UI 仅仅因为读取文件阻塞而锁定。
第二个问题是在发射器中使用new 和在接收器中使用delete 的机制似乎有点幼稚:我有效地将整个堆用作跨线程队列。
问题 1: Qt 是否有更好/惯用的方式来跨线程移动数据同时限制内存消耗?它是否有线程安全队列或其他可以简化整个事情的结构?
问题 2:我是否必须自己实现线程等?我不是重新发明轮子的忠实粉丝,尤其是在内存管理和线程方面。是否有更高级别的结构已经可以做到这一点,比如网络传输?
【问题讨论】:
-
关于问题2:看看QtConcurrent::run。它允许你异步执行一个函数(或成员函数)。
-
我建议使用工作线程(例如“详细描述”部分中的here)。关于堆分配,我看不到它的需要,只需传递一个 const ref。实现一个控制器(我想是你的 HexViewer)和工作线程,如示例所示
标签: c++ multithreading qt io