PDA

View Full Version : -how to run a function in separate thread



shivendra46d
23rd October 2013, 12:59
Hello
I want to run a function in separate thread because in that function there is very heavy calculation and it freezes my ui for the time, and also because it is taking too much time.
This is my function.


void SRP_Ray_Plot(double No_Of_Rays, double Max_Range,double Source_Depth,double Initial_Angle, double Angle_Difference);

and this function is currently being called on button click.

I tried to run with QtConcurent. Like this.

QFuture<void> future = QtConcurrent::run(SRP_Ray_Plot,SIP_number_of_rays, SIP_horizontal_range,SIP_source_depth,SIP_ray_init ial_angle,SIP_Angle_Difference);
But i get the following error

D:/Shivendra ]/SRP_24_Oct/mainwindow.h:42: QtConcurrent: No such file or directory

Please help me with this one.

toufic.dbouk
23rd October 2013, 13:06
I would create a class subclassing OObject and do the calculation there and run it as a separate thread ie. worker thread using MoveToThread() function.

Good Luck.

wysota
23rd October 2013, 13:11
Qt4 or Qt5?

shivendra46d
24th October 2013, 10:39
can any one tell me whats wrong in the following code
mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include<QThread>
#include <QDebug>
namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();

protected:
void changeEvent(QEvent *e);

private slots:
void on_pushButton_clicked();
void debug();

private:
Ui::MainWindow *ui;
};
class MyThread : public QThread
{
Q_OBJECT


public:
void run();

signals:

void v_update();
void value();
};


#endif // MAINWINDOW_H


mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
MyThread thread;
connect(&thread,SIGNAL(v_update()),this,SLOT(debug()));
}

MainWindow::~MainWindow()
{
delete ui;
}

void MainWindow::changeEvent(QEvent *e)
{
QMainWindow::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
ui->retranslateUi(this);
break;
default:
break;
}
}
void MainWindow::debug()
{
qDebug()<<"hello";
}

void MyThread::run()
{
for (int i=0;i<=10;i++)
{
emit this->v_update();

}
this->quit();
}

void MainWindow::on_pushButton_clicked()
{
MyThread thread;
thread.run();

}

spirit
24th October 2013, 11:13
MyThread thread; will be destroyed when it goes out of ctor.
You need to create an object in heap.

shivendra46d
24th October 2013, 12:55
even that too dont work. :(
Problem is that thread is no emitting the signal.

toufic.dbouk
24th October 2013, 13:39
Where are you connecting the threads signal to the debug slot ?
in the constructor giving it a reference of a thread?
But then in your onClickButton method you are creating another thread and not connecting signals and slots.
So easily solved by removing what you wrote in the constructor ie :


MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
MyThread thread;
connect(&thread,SIGNAL(v_update()),this,SLOT(debug ()));
}
Now in your OnClickButton method add the same code you deleted ie:

void MainWindow::on_pushButton_clicked()
{
MyThread thread;
connect(&thread,SIGNAL(v_update()),this,SLOT(debug ()));
thread.run();
}
Even for better practice create the thread in a heap rather than a stack.
Good Luck.

Radek
24th October 2013, 15:40
I haven't written Qt multithreaded apps so far. I didn't need them but, AFAIK from writing multithreaded apps under other environments...

MyThread must not be on the stack - neither in the ctor nor in the push button handler. The thread.run() triggers the thread and returns immediately. Therefore, the push button handler creates a thread, connects it, runs it but then kills it immediately and destroys the thread object - or rather crashes the app in Qt. See documentation of QThread.

(1) MyThread must be a member of MyWindow so that the thread object gets destroyed when MyWindow does (and MyThread has already finished). Even then MyThread needs some "stop me ASAP" flag which the thread is testing periodically and which you set in the MyWindow dtor and then wait until you get isFinished() from MyThread.
(2) Another possibility is creating MyThread dynamically, again with the "stop me ASAP" flag and setting the flag in the MyThread dtor (and wainting with return from the dtor until you get isFinished()).

toufic.dbouk
24th October 2013, 16:15
@Radek,
You went too far, his question was simple. And the mentioned method doesn't lead to a crash of the application if taken of properly.
Emit a finish signal when the threads job is done and connect it to the desired slot , maybe a deleteLater slot depending on the implementation.
Normally i wouldn't do threads in this way, i would subclass QObject and use moveToThread when needed then start the thread with the correct signals and slots to take care of managing and deleting properly.
Its a sure thing that its for the best to create it on the heap for several reasons.
The users method is not wrong but it has its own cases to use it same as all other implementations.

stampede
24th October 2013, 17:28
The users method is not wrong (...)
Yeah, except it doesn't run anything in separate thread this way:)
OP: can you answer wysota's question ? I think he wanted to help you with this error
QtConcurrent: No such file or directory

toufic.dbouk
24th October 2013, 18:34
...except it doesn't run anything in separate thread this way
Why ?
Deriving a class from QThread, re-implementing the QThread::run() method, and using QThread::start() to run it will make sure that that method is run in a different thread.
So all he has to do is create the thread in a heap and call start().

And yes he hasn't answered the main question i am still waiting whether he is using Qt4 or Qt5.

stampede
24th October 2013, 18:44
I mean this way, how it is currently implemented :) Anyway, i think it will be better for OP to use QtConcurrent and give QThread another try later.

toufic.dbouk
24th October 2013, 18:57
I agree with you.
My bad :) i was helping him step by step so i thought you meant the whole approach doesnt work...

shivendra46d
24th October 2013, 19:20
I am trying on both the version Qt 4 as well as on Qt 5

Hey can you tell me what i am doing wrong because when ever i try to use connect() signal slot in the call back of push button i get some kind of error why is it so ?

Added after 12 minutes:

This is for all those who want to use some thing like this to play with signal and slot and threads also

toufic.dbouk
24th October 2013, 19:20
Show us what you are doing and what are the errors ?
Check my previous posts they solve the problem.

Good Luck.

shivendra46d
24th October 2013, 19:22
Hey thanks a lot buddy
It solved the problem, but i want to do it more properly so please tell me
my email id
shivendra46d@gmail.com
i would like to keep in touch with you pelople

toufic.dbouk
24th October 2013, 19:25
You can keep in touch on this forum its more helpful than an email over gmail :)

shivendra46d
25th October 2013, 07:34
does running a function in separate thread which carries out heavy computation and which when in main thread freezes the ui . will help in over coming the problem? is there any other way to remove freezing of ui?
i went through some tutorial but not of good help

stampede
25th October 2013, 07:49
does running a function in separate thread which carries out heavy computation and which when in main thread freezes the ui . will help in over coming the problem?
Yes, if implemented properly. Keep in mind that you will have to synchronize with main thread if you want to display the results.
If it is only a single function, I'd use QtConcurrent to run it. Few lines of code and you have your processing done in separate thread.

toufic.dbouk
25th October 2013, 07:50
other way to remove freezing of ui?
Depends on what is causing the GI freezing in your heavy computation method.

does running a function in separate thread which carries out heavy computation and which when in main thread freezes the ui . will help in over coming the problem?
Yes, when you run it in a different thread obviously the main GUI wont freeze.

i went through some tutorial but not of good help
Read more tutorials, read Qt documentation and reference. Check this link for example Keeping the GUI Responsive (http://doc.qt.digia.com/qq/qq27-responsive-guis.html)

Good Luck.

wysota
25th October 2013, 08:22
I am trying on both the version Qt 4 as well as on Qt 5

In Qt5 your project file needs a "QT += concurrent" line for QtConcurrent to work.

As for running a function in a thread, if it is a fire-and-forget situation, the two easiest approaches are to use QtConcurrent:run() or QRunnable in case you have problems in assembling a proper direct call to QtConcurrent::run().

shivendra46d
28th October 2013, 05:16
I tried running in QTConcurrent my function

void SRP_Ray_Plot(double No_Of_Rays, double Max_Range,double Source_Depth,double Initial_Angle, double Angle_Difference);
like this

QFuture<void> future = QtConcurrent::run(SRP_Ray_Plot, number_of_rays, max_range, source_depth,initial_angle,Angle_Difference);

but it is giving me error


mainwindow.cpp:1155: error: no matching function for call to `run(<unknown type>, double&, double&, double&, double&, double&)'
in the include i tried using

#include<QTConcurent>
but it shows error no such file or directory
and when i use

#include <qtconcurrentrun.h>
the error about no such file is removed.
Where i am wrong ?

wysota
28th October 2013, 06:20
#include <QtConcurrentRun>

void SRP_Ray_Plot(double No_Of_Rays, double Max_Range, double Source_Depth, double Initial_Angle, double Angle_Difference) {
Q_UNUSED(No_Of_Rays); Q_UNUSED(Max_Range); Q_UNUSED(Source_Depth); Q_UNUSED(Initial_Angle); Q_UNUSED(Angle_Difference);
}

int main() {
QFuture<void> future = QtConcurrent::run(SRP_Ray_Plot, 1, 1, 1, 1, 1);
return 0;
}

QT = core
TEMPLATE = app
TARGET = concurrent