[Qt-interest] Basic QThread question

Sean Harmer sean.harmer at maps-technology.com
Thu May 13 14:15:28 CEST 2010


Hi Phil,

On Thursday 13 May 2010 11:17:51 Phil wrote:
> On Fri, 7 May 2010 06:14:02 pm Sean Harmer wrote:
> 
> I'm almost afraid to have to ask for some more hand-holding.

No worries.

> The code that Sean kindly put together for me does work correctly,
> however, there is a small complication. I'll try to explain this without
> too much code.
> 
> The main class, derived from QMainWindow has a drop down selection box.
> The item selected determines the variables sent to several functions. The
> hardware is then polled and the returned data forms part of further
> calculations.
> 
> I've pasted Sean's code into my selectItme function as follows:
> 
> void Pest::selectItem(const QString &listItem)
> {
>     DevicePoller poller;    //I think there may be a problem here
>     poller.stop();

Why are you making a DevicePoller on the stack here at all? The thread makes 
one for you which is all that you need.

>     //pass variables based on the selection to a calculation class
> 
>     //restart the thread timer
> 
>     //Sean's code follows
> 
>     // Get the worker thread to start but wait until the
>     // DevicePoller thread has actually been created.
>     m_workerThread->waitForStart();

No need to keep starting the thread. You should just do this once in your 
class' constructor or something similar. The thread should always stay 
running, you just need to start/stop the DevicePoller object that is a member 
of the thread class as needed.

>     // It is now safe to connect to the DevicePoller's signals
>     connect( m_workerThread->poller(), SIGNAL( value( int ) ),
>              this, SLOT( processData( int ) ) );

Again, just connect to the signal once somewhere convenient.

>     // Note that starting the worker thread does not automatically
>     // start the timer that controls the polling. We now do this
>     // explicitly so that we do not miss any data that could have
>     // been collected between the calls to waitForStart() and connect.
>     // We can either call the DevicePoller::start() slot using a
>     // singleshot timer or invokeMethod.
>     QTimer::singleShot( 0, m_workerThread->poller(), SLOT( start() ) );
> }
> 
> This works perfectly the first time, however, a subsequent selection fails.
> It seems that the timer thread does not restart.

That is because you never actually stopped the thread and nor should you need 
to. Do not get confused between starting/stopping the thread and 
starting/stopping the DevicePoller object that actually does the work. There 
is no harm in leaving the thread running the entire time.

> No doubt the answer is obvious, but not to me. Can anyone help, please?

Try something along these lines:

class Pest : public QMainWindow
{
Q_OBJECT
public:
    Pest( QWidget* parent = 0 )
    : QMainWindow( parent ),
      m_workerThread( new PollingThread( this ) )
    {
        // Start the thread
        m_workerThread->waitForStart();

        // Make connections
        DevicePoller* poller = m_workerThread->poller();
        connect( poller, SIGNAL( value( int ) ), 
                     this, SLOT( processData( int ) ) );
        connect( this, SIGNAL( stop() ), poller, SLOT( stop() ) );
        connect( this, SIGNAL( start() ), poller, SLOT( start() ) );

        // Start the polling off. 
        // Just emit the stop() signal to stop it when needed.
        emit start();
    }

signals:
    void start();
    void stop();

public slots:
    void processData( int ) { // Do something useful }
};


Does that help? If not can you specify the desired flow of logic more 
precisely? So now you get your data delivered to your processData(int) 
function and you can simply emit the start() or stop() signals of the Pest 
class to start/stop the poller respectively.

Just be aware that if your processing functions take a very long time to run 
then your device could be polled again unless you tell it to stop.

HTH,

Sean



More information about the Qt-interest-old mailing list