[Qt-interest] connection between qthreads blocks my gui
Sean Harmer
sean.harmer at maps-technology.com
Wed Dec 15 16:02:48 CET 2010
Hi,
On Wednesday 15 December 2010 13:22:10 franki wrote:
> Wednesday 15 of December 2010 10:07:21 Sean Harmer napisał(a):
> > This should really be on an FAQ somewhere. The section of the docs you
> > need to read and understand is this:
> >
> > http://doc.qt.nokia.com/latest/threads-qobject.html
> >
> > As K Frank and others mentioned you need to be careful if you want to put
> > slots directly onto your QThread class. To avoid confusion it is often
> > clearer to use a worker QObject that lives within and has affinitiy with
> > your QThread object.
> >
> > Please see the attached example to see how this pattern generally works.
> > We do exactly this kind of thing over rs232 comms too and it works a
> > treat.
>
> Well this example seems to be far more advanced than what I was doing so
> far. Correct me please if I'm wrong.
Not so different I think.
> You create DataProcessor object which has affinity to main thread, but in
> constructor you create another thread from PollingThread, and you store it
> in private variable
> PollingThread* m_workerThread
> This m_workerThread creates DevicePoller which is simply object living
> inside new thread and doing all rs232 communication (invoked by QTimer).
> (in my case it would be rs232Manager that talks to devices on this
> separate thread, and then sends the results to my guiClass - an equivalent
> of DataProcessor) Now, talking to device through rs232 must be serialized,
> which means one operation at the time, so DevicePoller living in QThread
> queries devices and sends results to DataProcessor one by one.
Correct.
> To sum up, in the end we have two threads, one is main thread where
> DataProcessor object lives, the second one is thread subclassed from
> QThread, which has an object DevicePoller which queries devices and sends
> results to main thread.
Correct.
> If it's correct (and I'm not sure I got the hang of it) it seems there is
> small mistake inside DataProcessor::DataProcessor constructor when you
> connect SIGNAL, the sender object should be m_workerThread->m_poller
> instead of m_workerThread->poller()
I am not sure what you mean here since you said replace something with the
same thing? At any rate I tink the example is correct since the object doing
the work is not the QThread sub-class but is indeed the DevicePoller object.
I guess I am what K Frank was calling a purist ;-) I like to think of QThreads
and their sub-classes as objects for managing threads of execution not for
actually doing any work within that thread. In this mindset the QThread::run()
function becomes exactly analogous to main() but in the context of the worker
thread which that object is managing. This also:
* keeps the QThread sub-classes very simple by separating concerns
* makes you worker object reusable in other threading contexts since it is not
tied to any particular thread. For example imagine you suddenly have to manage
5 of your devices. It is likely wasteful to have a thread for each device.
Instead you could simply create 5 worker objects in your one helper thread.
* makes it clearer in which thread of execution the work will actually be
done.
> It is a fine example to query devices, althought in my case it should also
> contain some signal-slot connection in opposite direction. Because when
> user twists a QDial (wich has tracking on) this object needs to send lets
> say 50 requests to device to change lets say voltage smoothly from the
> value QDial was set at the beginning to the new position. In that case
> worker thread will have to queue these operation and perform it one by
> one.
Well that's easy add a slot to the DevicePoller object (or whatever you call
the worker object that lives in your helper thread) and connect a signal on an
object in your main thread to it. The only decision you have to make is where
do you do the calculation to issue the individual steps. You could either:
a) Break down the change into steps in the main thread object as you say and
issue the changes one per signal to the worker object in the other thread.
b) Issue a single change value type signal from your main thread object and
have the worker object in the other thread calculate what incremental steps to
take.
Either way will work.
HTH,
Sean
More information about the Qt-interest-old
mailing list