Асинхронный запуск в Qt

Иногда необходимо выполнить достаточно длительный код в отдельном потоке, что бы не терять отзывчивость интерфейса в программе.

Обычно для этих целей используют два подхода:

  • наследование от QThread;
  • подход создания объекта рабочего и помещение его в отдельный поток.

Оба они приведены в документации к QThread, изначально второй подход был описан в How To Really, Truly Use QThreads; The Full Explanation.

Это конечно все здорово, но хочется простые вещи делать просто и с наименьшем количеством кода. И тут нам может помочь асинхронный запуск.

Асинхронный запуск в Qt представлен функцией QtConcurrent::run которая входит в состав API высокого уровня многопоточного программирования QtConcurent.  QtConcurrent::run достаточно хорошо описано, я лишь хочу продемонстрировать связку QtConcurrent::run, QFutureWatcherQEventLoop для создания последовательного когда не блокирующего 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();
}
Реклама