Qt-interest Archive, August 2007
stopping + deleting QTimer
Message 1 in thread
Hey,
right now I'm using a singleShot Timer to run a initialization method
once my QThread enters its event loop. Within this init() method I
initialize an QTimer(this) object.
The problem is: The QTimer keeps running after the QThread event loop quits.
I can't stop and I can't delete the QTimer object from outside the
event loop (after the exec() line in run())
Any ideas?
Jens
--
[ signature omitted ]
Message 2 in thread
On fredag den 24. August 2007, Jens Luedicke wrote:
> Hey,
>
> right now I'm using a singleShot Timer to run a initialization method
> once my QThread enters its event loop. Within this init() method I
> initialize an QTimer(this) object.
>
> The problem is: The QTimer keeps running after the QThread event loop
> quits. I can't stop and I can't delete the QTimer object from outside the
> event loop (after the exec() line in run())
Show us the code.
Bo.
--
[ signature omitted ]
Message 3 in thread
On 8/24/07, Bo Thorsen <bo@xxxxxxxxxxxxxxxxxxxxx> wrote:
> Show us the code.
>
here it is:
void MyThread::run() {
qDebug("%s", Q_FUNC_INFO);
QTimer::singleShot(0, this, SLOT(init()));
// exec event loop
exec();
// do cleanups
cleanup();
}
void MyThread::init() {
// ... init a few variables
// Update Timer:
updateTimer = new QTimer(this);
connect(updateTimer, SIGNAL(timeout()), this, SLOT(doUpdate()));
updateTimer->start(updateTimeout);
}
void MyThread::cleanup() {
qDebug("%s", Q_FUNC_INFO);
// routeUpdateTimer->stop(); // <-- problem 1
// delete routeUpdateTimer; // <-- problem 2
// routeUpdateTimer = 0;
}
Jens
--
[ signature omitted ]
Message 4 in thread
Hello,
I've had a similar problem.
The trick is that you start a new thread in your main thread for
example. So the new thread is using the eventloop of the thread in which
you created the new thread. To make sure the new thread uses his own
eventloop(exec()), you can add in the constructor of 'MyThread' this line:
moveToThread(this);
And now the timer you create with the new thread as a parent will use
your new thread's eventloop!
This is nowhere mentionned in the docs I think, but it should be.
greetz,
Tom,
--
[ signature omitted ]
Message 5 in thread
On 24.08.07 10:27:47, Jens Luedicke wrote:
> On 8/24/07, Bo Thorsen <bo@xxxxxxxxxxxxxxxxxxxxx> wrote:
> > Show us the code.
> here it is:
>
> void MyThread::run() {
> qDebug("%s", Q_FUNC_INFO);
>
> QTimer::singleShot(0, this, SLOT(init()));
>
> // exec event loop
> exec();
>
> // do cleanups
> cleanup();
> }
>
> void MyThread::init() {
> // ... init a few variables
>
> // Update Timer:
> updateTimer = new QTimer(this);
> connect(updateTimer, SIGNAL(timeout()), this, SLOT(doUpdate()));
> updateTimer->start(updateTimeout);
> }
>
> void MyThread::cleanup() {
> qDebug("%s", Q_FUNC_INFO);
>
> // routeUpdateTimer->stop(); // <-- problem 1
>
> // delete routeUpdateTimer; // <-- problem 2
> // routeUpdateTimer = 0;
> }
But thats nt the timer you created in init(), the variable is named
differently. If thats not the problem: Does cleanup() get called at all?
how do you exit the event loop of your thread?
Andreas
--
[ signature omitted ]
Message 6 in thread
On 8/24/07, Andreas Pakulat <apaku@xxxxxx> wrote:
> But thats nt the timer you created in init(), the variable is named
> differently. If thats not the problem: Does cleanup() get called at all?
> how do you exit the event loop of your thread?
A mistake while preparing the code example :)
I start and stop my Thread with signals (button clicks) connected to the
start() and quit() slots the Thread.
Yes, cleanup() is called after exec() in run() returns.
Jens
--
[ signature omitted ]
Message 7 in thread
On a side note:
you dont really need to do this:
routeUpdateTimer->stop(); // <-- problem 1
since the event loop is done anyways,
and you don't need to do this:
delete routeUpdateTimer; // <-- problem 2
since you gave the timer a parent:
updateTimer = new QTimer(this);
so whenever "this" will be destroyed, the QObject system will automatically delete the Timer.
http://doc.trolltech.com/4.3/objecttrees.html
Cheers,
Peter
Message 8 in thread
On Friday 24 August 2007 10:27:47 Jens Luedicke wrote:
> On 8/24/07, Bo Thorsen <bo@xxxxxxxxxxxxxxxxxxxxx> wrote:
> > Show us the code.
>
> here it is:
>
> void MyThread::run() {
> qDebug("%s", Q_FUNC_INFO);
>
> QTimer::singleShot(0, this, SLOT(init()));
>
> // exec event loop
> exec();
>
> // do cleanups
> cleanup();
> }
>
> void MyThread::init() {
> // ... init a few variables
>
> // Update Timer:
> updateTimer = new QTimer(this);
> connect(updateTimer, SIGNAL(timeout()), this, SLOT(doUpdate()));
> updateTimer->start(updateTimeout);
> }
>
> void MyThread::cleanup() {
> qDebug("%s", Q_FUNC_INFO);
>
> // routeUpdateTimer->stop(); // <-- problem 1
>
> // delete routeUpdateTimer; // <-- problem 2
> // routeUpdateTimer = 0;
> }
>
>
> Jens
Seems you're hitting the bug described here:
http://trolltech.com/developer/task-tracker/index_html?id=169376&method=entry
It was fixed in 4.3.1, which version of Qt are you using?
--
[ signature omitted ]
Message 9 in thread
Suppose you have:
class MyThread: public QThread {
...
void run() {
...
exec();
...
}
...
};
Object of MyThread class is created in MainThread (unless you start
thread from another one - not Main thread). The key point that
everything you run before invoking
QThread::exec()
in
MyThread::run()
is supposed to be running in MainThread. On the other Communication
between Thread and MainThread should be done via connections of Signals
<-> Slots (the safest ones).
Event may be emitted in MainThread and will be put into a stack of
Events Loop in Thread in case there is connection. Thus if there is
already any events in Stack on QThread::exec() invocation - they will be
processed first.
Thus solution: put some Event into Stack of Events, for example use
external small class:
class ThreadSemaphore: public QObject
{
Q_OBJECT
signals:
void started();
public:
// Constructor, Destructor (empty ones... no job is done)
inline void start() { emit started(); }
};
----
MyThread::MyThread( ...)
{
...
poThreadSemaphore_ = new ThreadSemaphore();
connect( poThreadSemaphore_, SIGNAL( started()),
this, SLOT( onStartedThread()) );
}
MyThread::~MyThread() { delete poThreadSemaphore_; }
...
void MyThread::run() {
// Next line will emit signal in MainThread and Event will be kept in
Thread Events stack unless exec() is invoked.
poThreadSemaphore_->start();
exec();
// Thread postprocessing
}
void MyThread::onStartedThread() {
// Start work that is supposed to be done inside thread having already
Events loop invoked
// [note: don't forget to call quit() once you are done working with thread
}
...
Now QTimer is not needed any more.
Samvel
Jens Luedicke wrote:
> Hey,
>
> right now I'm using a singleShot Timer to run a initialization method
> once my QThread enters its event loop. Within this init() method I
> initialize an QTimer(this) object.
>
> The problem is: The QTimer keeps running after the QThread event loop quits.
> I can't stop and I can't delete the QTimer object from outside the
> event loop (after the exec() line in run())
>
> Any ideas?
>
> Jens
>
>
--
[ signature omitted ]
Message 10 in thread
On 8/24/07, Samvel Khalatian <ksamdev@xxxxxxxxx> wrote:
> Suppose you have:
>
> class MyThread: public QThread {
> ...
> void run() {
> ...
> exec();
> ...
> }
> ...
> };
>
> Object of MyThread class is created in MainThread (unless you start
> thread from another one - not Main thread). The key point that
> everything you run before invoking
> QThread::exec()
> in
> MyThread::run()
> is supposed to be running in MainThread. On the other Communication
> between Thread and MainThread should be done via connections of Signals
> <-> Slots (the safest ones).
> Event may be emitted in MainThread and will be put into a stack of
> Events Loop in Thread in case there is connection. Thus if there is
> already any events in Stack on QThread::exec() invocation - they will be
> processed first.
AFAICS this is the same as running an init slot via Single Shot once
the Thread Event Loop
runs. My Problem is starting and stopping QTimer's within the MyThread context:
From the docs:
"To start an event loop from a non-GUI thread, use QThread::exec(). Qt
uses the the timer's thread affinity to determine which thread will
emit the timeout() signal. Because of this, you must start and stop
the timer in its thread; it is not possible to start a timer from
another thread."
Jens
--
[ signature omitted ]