[Qt-interest] Basic QThread question

Sean Harmer sean.harmer at maps-technology.com
Thu May 6 11:34:00 CEST 2010


Hi Phil,

On Thursday 06 May 2010 08:59:02 Phil wrote:
> On Tue, 27 Apr 2010 05:40:33 pm Sean Harmer wrote:
> > Hi,
> > 
> > It is probably best to use a QTimer with a 1s timeout value in your
> > worker thread. Then connect the timeout signal to a slot that queries
> > your device
> > 
> >  and then emits a signal value( int x ) say that you have connected to in
> >  the main thread.
> > 
> > You just need to be careful about which thread context your slot gets
> > 
> >  called in because the thread object will have affinity with the main
> >  thread not itself. The easiest way to do this is to create an object in
> >  the run() function of your QThread subclass that does the actual work
> >  rather than having the QThread class do the work.
> > 
> > Something like this:
> > 
> > class DevicePoller : public QObject
> > {
> > Q_OBJECT
> > 
> > public:
> >     DevicePoller( QObject* parent = 0 )
> >     
> >     : QObject( parent ), m_timer( new QTimer( this ) )
> >     
> >     {
> >     
> >         connect( m_timer, SIGNAL( timeout() ), SLOT( poll() ) );
> >         m_timer->start( 1000 );
> >     
> >     }
> > 
> > public slots:
> >     void poll()
> >     {
> >     
> >         // Talk to your device here
> >         ...
> >         int x = ...
> >         
> >         // Let the world know the value retrieved
> >         emit value( x );
> >     
> >     }
> > 
> > signals:
> >     void value( int x );
> > 
> > private:
> >     QTimer* m_timer;
> > 
> > };
> > 
> > 
> > class PollingThread : public QThread
> > {
> > Q_OBJECT
> > 
> > public:
> >     PollingThread( QObject* parent = 0 )
> >     
> >     : QThread( parent )
> >     
> >     {}
> >     
> >     DevicePoller* poller() const { return m_poller; }
> > 
> > protected:
> >     virtual void run()
> >     {
> >     
> >         // Create an object to do the polling
> >         m_poller = new DevicePoller;
> >         
> >         // Start the event loop
> >         exec();
> >         
> >         // Clean up
> >         delete m_poller;
> >         m_poller = 0;
> >     
> >     }
> > 
> > private:
> >     DevicePoller* m_poller;
> > 
> > };
> > 
> > 
> > Then in your main thread somewhere have something like this:
> > 
> > DevicePoller* m_workerThread = new DevicePoller( this );
> 
> The above line has been corrected to PollingThread* etc.
> 
> > // Will use a Qt::QueuedConnection as objects live in different threads
> 
> This is the area where I'm having trouble. Is the following line correct?
> 
> > connect( m_workerThread->poller(), SIGNAL( value( int ) ),
> > 
> >          this, SLOT( processValue( int ) ) );

Yes this is correct as far as I can tell. 

> Isn't the polling done in DevicePoller-> poll()? 

Yes it is but the DevicePoller::poll() function polls your device and then 
emits a signal with the collected value.

All you have to do is fill in the gaps in DevicePoller::poll() that actually 
talks to your device and extracts the value. This is then passed to your main 
thread for further processing by emitting it in the value( int ) signal.

As the DevicePoller and your MainWindow (or whatever object you have in your 
main thread) live in different threads, Qt knows to use a 
Qt::QueuedConnection.

> If I do create a poller
> function then I'm greeted with an error message stating:
> 
> "invalid use of void expression"

I do not understand what you mean by this. Can you post the code please?

> If I substitute "DevicePoller" for " m_workerThread->poller()" then the
> programme runs but not as a thread. The GUI is still blocked each second.

As expected as DevicePoller is not a thread. You need to create a 
PollingThread and connect to the value(int) signal emitted by the 
m_workerThread->poller() then start the worker thread.

> I'm still confused and, as always, any help will be greatly appreciated.

No worries. It is tricky to get to grips with. If you can post some more code 
from yoru main thread where you create the worker thread, connect the signal, 
start the worker thread, and where you process the emitted values that would 
help us to isolate the problem.

Cheers,

Sean



More information about the Qt-interest-old mailing list