PDA

View Full Version : [Article] How to QProcess in QThread



Raccoon29
27th November 2009, 15:52
Hello,

I googled a lot and went all over the internet (and Qt documentation) trying to find a quick solution, but I had no luck, so eventually I had to figure it out by myself.
This post is meant for this: just to give some quick reference to those are experiencing the same problem and need a fast idea of the solution.
Furthermore I saw many threads (not here) unanswered for this question, so I'm trying to give an answer (that at least for me worked).

I spent these days several hours trying to figure out how to use a QProcess object in a different thread without having qt complaining:

Cannot create children for a parent that is in a different thread.
because I was trying to create a QProcess to launch an external application from a different QThread than the main one.

This error pops up because with


MyThread::MyThread():QThread()
{
process=new QProcess(this); // QProcess process; in the class
}

we are trying to tell that QProcess object's parent is our QThread subclass, but actually this QProcess object lives in the different thread we are going to launch, while MyThread object is, presumably, in the main thread. Actually different threads, Qt doesn't like this.

Solution is quite easy, but I was so fretful that I didn't notice it.
To get it work is just required to use the new thread as a new event loop (besides it is), and declare QProcess in the run() method instead of allocate it dinamically as a MyThread member pointer:


// this is all the class is made of
void MyThread::run()
{
QProcess p;
connect(&p,SIGNAL(finished(int)),this,SLOT(quit()));
p->start("extprogram.exe");
exec();
}

p doesn't go prematurely out of scope until the end because exec() enters event loop and prevent it from being destroyed.
When process finishes execution, the connection calls the QThread's quit() slot that ends the thread; place a connection to the MyThread finished() signal in the main thread to know when it is over.

It was such a simple answer, I can't believe it took so much time to get fixed...
Maybe I am a dumb, but with this I hope to agile someone else's work.

Of course every comment on this is welcome.
HTH

wysota
27th November 2009, 16:24
I have one comment. Why spawn a new thread just to spawn a new process? In the situation described the thread does completely nothing - QProcess could have been created and started in the main thread without any loss of functionality. Or maybe I just don't see something...

Raccoon29
27th November 2009, 16:57
Yes S.Wysota, you are right: in this case QThread is useless, but this is meant to be a basis to use to build on.
For example, I had to make a background process that had to backup all the databases of the program, so it had to call mysqldump batching through every database; in this situation QProcess and QThread seems quite suitable to me.
On the other hands QProcess may be substituted by a custom user class that does more sophisticated code (as I did, by the way).

wysota
27th November 2009, 19:08
For example, I had to make a background process that had to backup all the databases of the program, so it had to call mysqldump batching through every database; in this situation QProcess and QThread seems quite suitable to me.

How come? Was your thread doing something while the external process was running?

Raccoon29
28th November 2009, 20:36
Was your thread doing something while the external process was running?
Well... actually it doesn't. It waits the process is over to launch the next one... maybe I could add some controls to make a progress bar...
You make me wonder. Do you think QThread is useless here and everything could be done just using signals/slots? :eek:

wysota
28th November 2009, 20:56
Do you think QThread is useless here and everything could be done just using signals/slots? :eek:

Yes, it's completely useless. Adding a progress bar or something wouldn't change anything, you can (and should) still do it in the main thread. You can read my article in Qt Quarterly about Responsive GUIs to get some ideas. I don't say your article is bad, I say you should give a useful example.

Raccoon29
30th November 2009, 08:22
Got it :)

BTW: in a code comment I wrote "QProcess process; in the class", it's a typo: to be allocated it must be a pointer, so: "QProcess *process; in the class"... but I can't edit it anymore.