Solved Why QtConcurrent::run freezing my program?
-
I read QString from the database which has a lot of data
I want to split QString line by line and then use it,
When I use the for to split it, my app freezes and doesn't work,
I found that the run function QtConcurrent :: run a function in a separate thread
I did as below, but my application still freeze when calling function readfilevoid MainWindow::getData(){ QString getRecord=dbFile->getRecord(IdGet); QFuture<void> t1 = QtConcurrent::run(demoSimple,&ZoomScrollTrack2::readfile, getRecord); t1.waitForFinished(); } void Track::readfile(QString Record){ for(int u=0;u<Record.size();u++){ QStringList line=Record.split("#"); qDebug()<<"record list"<<line; } }
I try to use this way but I have error (no matching function for call to run)
QFuture<QList<QString>> future = QtConcurrent::run(IdGet, &QString::split, '#'); QList<QString> result = future.result(); qDebug()<<"list"<<result;
Is QtConcurrent::run function is a good way for my action or I need to use QThread with subclass?
-
Since you're directly waiting for the result your gui freezes. You should connect to the QFuture signals and/or use QFutureWatcher. See https://doc.qt.io/qt-5/qtconcurrent-index.html
-
@isan additional to what @Christian-Ehrlicher said, you may want to consider using splitRef('#') it returns a QVector<QStringRef> instead of a QList<QString> it is significantly faster, but it depends on the lifetime of the original QString!
-
@isan You need to use
QFutureWatcher
in combination withQEventLoop
to not lock you main thread.
Something like this:// start process in another thread QFuture<void> future = QtConcurrent::run(demoSimple,&ZoomScrollTrack2::readfile, getRecord)); QFutureWatcher<void> watcher; QEventLoop loop; // QueuedConnection is necessary in case the signal finished is emitted before the loop starts // (if the task is already finished when setFuture is called) connect(&watcher, SIGNAL(finished()), &loop, SLOT(quit()), Qt::QueuedConnection); watcher.setFuture(future); qDebug()<<"wait for result"; // passive wait until QFuture is finished loop.exec(); qDebug()<<"done";
-
Thanks for your help
It works, but it takes a few minutes, is there a better way to make it faster? -
@isan compiling and running it in release mode will make it a good bit faster.
besides that, truncating your QString beforehand and running multiple QtConcurrent each one with part of the original string?
-
@kromignon said in Why QtConcurrent::run freezing my program?:
You need to use QFutureWatcher in combination with QEventLoop to not lock you main thread.
This contradicts the whole idea to move the heavy work into an own thread...
-
@isan said in Why QtConcurrent::run freezing my program?:
for(int u=0;u<Record.size();u++){
QStringList line=Record.split("#");
qDebug()<<"record list"<<line;I hope this is not your real function since it basically does Record.size() times the same.
-
@christian-ehrlicher
yes you said right, it should work without for()