[Qt-interest] connection between qthreads blocks my gui

franki franki at franki.eu.org
Wed Dec 15 01:38:27 CET 2010


Wednesday 15 of December 2010 00:15:06 K. Frank napisał(a):
> Hello Marek -
>

Hello,

For the moment being, my rs232Manager can do only one thing at the time, eg. 
it writes to device, waits for response, then it takes next job, so it is 
convenient to have QThread run this class with it's own eventDispatcher. 
However who knows what may be next, app should grow over the time, or at least 
I hope so, and if it is a blessed way then i try to instantiate rs232Manager 
inside class derived from QThread.
But then... just quick thought:
connect(guiClass,SIGNAL(doSomething()),rs232Thread->rs232Manager,SLOT(doWork()))
Or should I do some function in rs232Thread to call rs232Manager to get the 
job done? 

On the other hand, I don't have anything against moving rs232Manager object to 
thread, and  I don't know what other functions would I implemet in 
rs232Thread (derived from QThread) providing that pure QThread object has 
it's own exec loop (since Qt 4.4 as I read), maybe for me it simply over the 
top to subclass the QThread.
Anyway, will try this tomorrow ;)

many thanks
Marek

> 2010/12/14 franki <franki at franki.eu.org>:
> > Tuesday 14 of December 2010 20:06:58 J-P Nurmi napisał(a):
> >> On Tue, Dec 14, 2010 at 8:25 PM, franki <franki at franki.eu.org> wrote:
> >> > ...
> >> > I have some gui class (mainClass), inside that class I created two
> >> > classes which subclass QThread, one of which is sending/receiving data
> >> > from rs232, lets say rs232Thread, second one is sending signal to
> >> > start reading from rs232,lets say cronThread. Connection is defined
> >> > inside mainClass like this:
> >> > connect(cronThread,SIGNAL(startChecking()),rs232Thread,SLOT(readWrite(
> >> >)), Qt::QueuedConnection)
> >> >
> >> > Problem is, that this readWrite function blocks my entire gui when
> >> > running, and as I read somewhere in case of QueuedConnection, the SLOT
> >> > is executed inside receiver's thread, so why is this blocking my gui?
> >> > ...
> >> > What am I doing wrong? Is this a problem that connection between this
> >> > two threads is defined inside mainClass (which is gui thread) ? Or
> >> > there is something else?
> >>
> >> Hi,
> >>
> >> Be careful with having slots in QThread subclasses. Check this
> >> arcticle: http://labs.qt.nokia.com/2010/06/17/youre-doing-it-wrong/.
> >
> > I have read this
> > ...
> > So now I see some options
>
> Warning -- I haven't fully absorbed what you are trying to do,
> so my general comments may not apply precisely to your
> specific situation.
>
> > 1. Simplest (but I'm not sure if it meets all my needs) is to call
> > moveToThread(this) inside class contructor, then all functions defined in
> > class will move to separate thread and QueuedConnection signal-slot
> > should work
>
> This should work.  I think it's a fine idiom for using queued
> connections in a QThread-derived class.
>
> It has the disadvantage that your QThread-derived class -- let's say
> Rs232Thread -- now mixes together two separate concerns:  First, the
> class manages a thread of execution (because that's what QThread
> does); and second the class manages RS-232 communication
> (because presumably that's what Rs232Thread does).
>
> It has the advantage that it is somewhat less verbose than a design
> in which you break out the RS-232 management into another class.
>
> (Object-oriented purists would consider the disadvantage sufficiently
> compelling to avoid this approach, but I'm not sure that I would go
> so far as to say that this approach is "doing it wrong.")
>
> > 2. Rewite code to make my classes derived from QObject, as I need them to
> > send signals after work done, and slots are needed of course, and after
> > creating the object move class to separate thread
>
> I imagine here that you define two QObject-derived classes:  Rs232Manager,
> and Rs232Cron.  This is the separation-of-concerns approach where you
> don't mix the "real" work done by your classes (the RS-232 stuff) with
> thread management (the job of QThread).
>
> Note, however, that you can avoid an explicit call to moveToThread by
> using what I think is a common Qt threading idiom:  Derive a class,
> Rs232Thread, from QThread, and have Rs232Thread instantiate an
> Rs232Manager in its run method.  The Rs232Manager now has affinity
> for the thread of execution managed by Rs232Thread, so you signal
> and slot connections to Rs232Thread will be queued connections, and
> won't block your main gui thread.
>
> This is a little more modular that option 1 (keeps the purists happy),
> but is a little more verbose.
>
> > 3. Someone has mentioned using RegisterdThreads and then all slots will
> > be executed in just created thread
>
> I don't see the need for this given what (I think) you're trying to do.
>
> > 4. for these people who were claiming that they never have to use
> > moveToThread I suppose they were doing some sort of job queue on their
> > own, right? So far I was using some flags (regular variables) or
> > QWaitCondition in endless loop inside run() function, but I found it
> > cumbersome when dealing with many jobs to do.
>
> I think in order not to need to call moveToThread, you need to use option
> 2. If you don't want your gui thread to block, your RS-232 slots need to be
> called over queued connections, so your Rs232Manager class has to have
> affinity for a thread of execution other than the gui thread.  So it either
> needs to be instantiated in another thread (option 2) or it needs to be
> moved to another thread by calling moveToThread (e.g., option 1).
>
> > In the end, what would be the best way?
>
> Assuming that your needs are a simple as you describe, I think both
> options 1 and 2 are fine.  If your application is fairly small (and not
> expected to grow much over time), I would lean towards options 1
> for its economy.  If your application is larger or is likely to need
> ongoing maintenance, I would lean towards options 2 for its greater
> modularity.
>
> > What I need to implement in app is like this.
> > When it initialize app, it queries all devices through rs232 which takes
> > about 10 seconds. This is easy - put all work inside run() of a rs232
> > thread and receive signals notifying about every device. Such a general
> > checking is invoked every five minutes, so I have function that sets
> > variables like checkSomething and starts rs232 thread (if its not
> > working). However, between these general checkings, if user move QDial
> > (or press button which has autoRepeat) on the gui it has to send signals
> > to change something in device, because it takes about 100 miliseconds for
> > rs232 to accomplish single change, and QDial has tracking enabled I need
> > rs232 to buffer this subsequent changes and apply them to device without
> > gui freezing. So, the mechanism with queueing events for rs232 (which
> > works in separate thread) is very attractive to me, but question: am I
> > missing something, or should I go stright to number 2 solution?
> >
> > best regards
> > Marek
>
> Good luck.
>
>
> K. Frank
>
> _______________________________________________
> Qt-interest mailing list
> Qt-interest at trolltech.com
> http://lists.trolltech.com/mailman/listinfo/qt-interest






More information about the Qt-interest-old mailing list