Иногда необходимо выполнить достаточно длительный код в отдельном потоке, что бы не терять отзывчивость интерфейса в программе.
Обычно для этих целей используют два подхода:
- наследование от QThread;
- подход создания объекта рабочего и помещение его в отдельный поток.
Оба они приведены в документации к QThread, изначально второй подход был описан в How To Really, Truly Use QThreads; The Full Explanation.
Это конечно все здорово, но хочется простые вещи делать просто и с наименьшем количеством кода. И тут нам может помочь асинхронный запуск.
Асинхронный запуск в Qt представлен функцией QtConcurrent::run которая входит в состав API высокого уровня многопоточного программирования QtConcurent. QtConcurrent::run достаточно хорошо описано, я лишь хочу продемонстрировать связку QtConcurrent::run, QFutureWatcher, QEventLoop для создания последовательного когда не блокирующего UI
#include <QtCore/QThread> #include <QtCore/QEventLoop> #include <QtCore/QFutureWatcher> #include <QtConcurrent/QtConcurrentRun> #include <QtWidgets/QApplication> #include <QtWidgets/QLabel> #include <QtWidgets/QProgressDialog> class Foo { public: int bar () { QThread::sleep(10); return 5; } }; int main(int argc, char *argv[]) { QApplication a(argc, argv); Foo foo; QFutureWatcher<int> watcher; QEventLoop loop; QProgressDialog progress; progress.setRange(0,0); progress.setCancelButton(0); progress.show(); QObject::connect(&watcher, &QFutureWatcher<int>::finished, &loop, &QEventLoop::quit); watcher.setFuture (QtConcurrent::run(&foo, &Foo::bar)); loop.exec (); progress.close (); QLabel lbl; lbl.setText(QString("Result: %1").arg (watcher.result())); lbl.show(); return a.exec(); }