Sunday, June 1, 2008

Qt: simple example of use of QtConcurrent

In this example we assume that a function my_func takes a long time to run, and would cause the GUI to freeze if it were run in the main GUI thread. In order to avoid the GUI freezing, we run my_func in a separate thread. The GUI will be therefore be fully functional while my_func is running.

When this application launched, a small GUI will appear containing a single button. When the button is clicked, the function my_func is run in a separate thread. When the thread finishes running, a message appears on the screen.

This example makes uses QtConcurrent::run(), QFuture and QFutureWatcher, rather than just a QThread. Qt 4.4.0 or above is required.

This example consists of the following codes: main.C, user_def.h, window.C and window.h.

main.C

Here we define the time-consuming operation. In this example, it is just a summation.
#include <QApplication>

#include "window.h"
#include "user_def.h"

//----------------------------------------------------------------------------
//
// the user's time-consuming function
//
//----------------------------------------------------------------------------

void my_func(void)
{
// time-consuming code
double sum;
for (int i=0; i<100000; i++)
{
for (int j=0; j<100000; j++)
{
sum = sum * i / j;
}
}
}

//----------------------------------------------------------------------------
//
// main program
//
//----------------------------------------------------------------------------

int main (int argc, char **argv)
{
QApplication app(argc, argv);
Window window;
window.show();
window.setMaximumSize(window.minimumWidth(),
window.minimumHeight());
return app.exec();
}


user_def.h
#ifndef USER_DEF_H_
#define USER_DEF_H_

void my_func(void);

#endif /*USER_DEF_H_*/


window.C

Here we setup a very simple GUI just containing a single button. When the button is clicked, the time-consuming operation my_func is run in another thread when QtConcurrent::run() is called. We use a QFutureWatcher to monitor the state of the other thread. When the GUI thread receives a signal from the QFutureWatcher that the function has finished running, it displays a message on the screen using a QMessageBox.

#include "window.h"

//----------------------------------------------------------------------------
//
// the main GUI
//
//----------------------------------------------------------------------------

//------------
// constructor
//------------

Window::Window(QWidget *parent) : QWidget(parent)
{
setWindowTitle("Qt example 03");
runButton = new QPushButton("Run the function...");
connect(runButton, SIGNAL(clicked()),
this, SLOT(run_thread()));

QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(runButton);
setLayout(layout);

// create a QFuture and a QFutureWatcher

future = new QFuture<void>;
watcher = new QFutureWatcher<void>;

// display a message box when the calculation has finished

connect(watcher, SIGNAL(finished()),
this, SLOT(displayFinishedBox()));

}

//-----
// slot
//-----

void Window::run_thread()
{
*future = QtConcurrent::run(my_func);
watcher->setFuture(*future);
}

//----------------
// display message
//----------------

void Window::displayFinishedBox()
{
QMessageBox::information(this, tr("Qt Example 03"),
tr("The function my_func has finished."));
}


window.h
#ifndef WINDOW_H_
#define WINDOW_H_

#include <QPushButton>
#include <QThread>
#include <QHBoxLayout>
#include <QMessageBox>
#include <QtConcurrentRun>
#include <QFuture>
#include <QFutureWatcher>

#include "user_def.h"

class Window : public QWidget
{
Q_OBJECT

public:
Window(QWidget *parent = 0);

private:
QPushButton *runButton;
QFuture<void> *future;
QFutureWatcher<void> *watcher;

public slots:
void run_thread();
void displayFinishedBox();
};

#endif /*WINDOW_H_*/


This example can be compiled easily using:

qmake -project
qmake
make

5 comments:

Debayan said...

Very helpful. Thanks.

Olivier said...

many thanx really usefull example , i got it bookmarked =)

Anonymous said...

me too :)

Eduardo J. said...

Thanks. That´s very useful to satrt.

Isma said...

Thank you!
Exactly what I was looking for =)