updatethread
is-a qthread
sets qtimer
in updatethread::run()
calls slot updatethread::tick()
every t
ms. based upon condition need pause
thread , after some time based upon condition need wake up.
- is way doing
qtimer
thing okay ? or should movetick
coderun
, callqthread::start()
everyt
ms ? - how can pause , wake threads conditionally
- or should
stop()
qtimer ,start()
latter ?
first of all, shouldn't define slots on qthread
subclass , call them within run()
- slots executed (by performing cross-thread slot invocation) in context of thread owns updatethread
instance (the same 1 created it, unless called movetothread()
on it), not in context of thread represented updatethread
. remember mnemonic:
in
run()
,qthread::thread() != this
instead, define slots on qobject subclass create inside run()
.
ok, out of way, let's have @ timer. qtimer
documentation contains following:
in multithreaded applications, can use
qtimer
in thread has event loop. start event loop non-gui thread, useqthread::exec()
. qt uses timer's thread affinity determine thread emittimeout()
signal. because of this, must start , stop timer in thread; not possible start timer thread.
(emphasis mine) take particular note of last sentence.
the solution cross-thread call of qtimer::start()
, qtimer::stop()
. might know cross-thread signal/slot connections. uses same underlying mechanism, exposed in qmetaobject::invokemethod()
:
class updatethread : public qthread { q_object private: qobject * m_timer; // qobject* we're not tempted // call functions on qmutext m_mutex; // protects 'm_timer' public: explicit updatethread( qobject * parent=0 ) : qthread( parent ), m_timer( 0 ) {} // ... private: /* reimpl */ void run() { qtimer timer; // ...'timer' setup code goes here... { const qmutexlocker locker( &m_mutex ); m_timer = &timer; // publish 'timer' through 'm_timer' } // main code of run() exec(); // start event loop timer's timeout()s // , can receive cross-thread method calls { const qmutexlocker locker( &m_mutex ); m_timer = 0; // un-publish before delete `timer` } } public q_slots: void starttimer() { const qmutexlocker locker( &m_mutex ); if ( !m_timer ) return; // perform cross-thread method call: qmetaobject::invokemethod( m_timer, "start", qt::queuedconnection ); } void stoptimer() { const qmutexlocker locker( &m_mutex ); if ( !m_timer ) return; // perform cross-thread method call: qmetaobject::invokemethod( m_timer, "stop", qt::queuedconnection ); } };
now, how start/stop timer gui thread. asking alternatives.
move
tick()
coderun()
, callupdatethread::start()
everyt
milliseconds.this suboptimal, create , destroy threads every
t
ms. thread creation still expensive operation. also, ifupdatethread::run()
isn't done time next callstart()
, you'll lose timer ticks.updatethread
outlined above.this isn't bad, it's not idiomatic multithreading, i'd say. it's solution if timer fires that alone slow down gui thread somehow, though might lose timer ticks way, too.
qthreadpool
my favourite. move code performs
tick()
implementation ofqrunnable::run()
, , queue new runnable on thread pool whenever timer fires. in case, timer naturally live in gui thread, avoiding need cross-thead method calls outlined above. unless gui thread overloaded, won't miss timer ticks. free scaling number of cores in system (if don't want that, don't useqthreadpool::globalinstance()
create own instance , callsetmaxthreadcount(1)
).
Comments
Post a Comment