First of all, you do not have multithreading in your application. Your FileReader class is a subclass of QThread , but this does not mean that all FileReader methods will execute in another thread. In fact, all of your operations are performed in the main (GUI) thread.
FileReader should be a subclass of QObject , not QThread . Then you create a basic QThread object and move your worker (reader) to it using QObject::moveToThread . You can read about this method here .
Make sure you register the type FileReader::State using qRegisterMetaType . This is necessary so that the connections to the Qt signal slot work in different streams.
Example:
HexViewer::HexViewer(QWidget *parent) : QMainWindow(parent), _ui(new Ui::HexViewer), _fileReader(new FileReader()) { qRegisterMetaType<FileReader::State>("FileReader::State"); QThread *readerThread = new QThread(this); readerThread->setObjectName("ReaderThread"); connect(readerThread, SIGNAL(finished()), _fileReader, SLOT(deleteLater())); _fileReader->moveToThread(readerThread); readerThread->start(); _ui->setupUi(this); ... } void HexViewer::on_quitButton_clicked() { _fileReader->thread()->quit(); _fileReader->thread()->wait(); qApp->quit(); }
There is also no need to allocate data in a bunch:
while(!inFile.atEnd()) { QByteArray *qa = new QByteArray(inFile.read(DATA_SIZE)); qDebug() << "emitting dataRead()"; emit dataRead(qa); }
QByteArray uses implicit exchange . This means that its contents are not copied again and again when you pass a QByteArray object through read-only functions.
Change the code above and forget about manual memory management:
while(!inFile.atEnd()) { QByteArray qa = inFile.read(DATA_SIZE); qDebug() << "emitting dataRead()"; emit dataRead(qa); }
But in any case, the main problem is not multithreading. The problem is that the QTextEdit::insertPlainText not cheap, especially when you have a huge amount of data. FileReader quickly reads the file data and then floods your widget with new displayed pieces of data.
It should be noted that you have a very inefficient implementation of HexViewer::loadData . You insert char text data into a char, which allows QTextEdit constantly redraw its contents and freeze the GUI.
First you must prepare the resulting hexadecimal string (note that the data parameter is no longer a pointer):
void HexViewer::loadData(QByteArray data) { QString tmp = data.toHex(); QString hexString; hexString.reserve(tmp.size() * 1.5); const int hexLen = 2; for (int i = 0; i < tmp.size(); i += hexLen) { hexString.append(tmp.mid(i, hexLen) + " "); } _ui->hexTextView->insertPlainText(hexString); }
In any case, the bottleneck of your application is not reading files, but QTextEdit . Loading data in chunks and then adding them to the widget using QTextEdit::insertPlainText will not speed anything up. For files smaller than 1 MB, it’s faster to read the entire file at a time, and then set the resulting text for the widget in one step.
I suppose you cannot easily display huge texts larger than a few megabytes in size using the default Qt widgets. This task requires some non-trivial correspondence, which in the general case has nothing to do with multithreaded or asynchronous data loading. It's all about creating a complex widget that will not try to display its huge content right away.