PDA

View Full Version : QThread and QTimer



sivrisinek
29th April 2009, 17:09
Hi there,

i have a QTimer conflict within a ClassA inheriting from QThread. ClassA has a massive data processing routine, which we call from the QThread::run() in order to let it run with the Qt::LowPriority. This works fine. ClassA has a single instance during the whole runtime of the application.



class ClassA : QThread
{
public:
ClassA();
~ClassA();
InitGUI();
focusHasLeft();
focusHasCome();

protected slots:
void refreshTimerSlot(); // this eventually starts the thread for reload of data
threadFinished(); // this slot is connected to the "thread is finished" signal

private:
//start the thread with low priority.
startThread();

// QThread
void run(void); // this calls massiveDataReloadRoutine()
void massiveDatareloadRoutine();

QTimer refreshTimer;
}


ClassA has a refresh timer which is used update the GUI periodically. This timer is in conflict with the QThread giving the message


"QObject::startTimer: timers can not be started from another thread"

inside the debug window. As a result, I can not start and stop the timer, and it runs all the time. The timer slot is being called without a problem.



But the problem is, if a change focus from the view i want to stop the timer so that the updates should not steal processing time.

In order to to stop the timer i have tried:

1) to stop the timer in ClassA::run() -> did not work
2) to stop the timer in ClassA::focusHasLeft() -> did not work
3) to stop the timer in ClassA::threafFinished() -> did not work

What is wrong?

wysota
29th April 2009, 18:38
QObject affinity is to the thread that created the object. Therefore QThread (or its subclass) object and all its member variables belong to the thread that created that object and not to the thread the object controls. So you can't start/stop the timer that is a member variable of the class from within the run() method unless you either create the timer within the run() method or you change the affinity of the QThread object by using QObject::moveToThread().

sivrisinek
30th April 2009, 16:12
I have forgotten to mention that i have tried the moveToThread() solution. It did not work.

Since yesterday, i have redesigned the thread, defined new signals, but i receive a compiler error (C2594 ambiguous conversion) during compilation of the moc file.

The error points to the following line in moc_ClassA.cpp:


void ClassA::signal1()
{
ERROR-> QMetaObject::activate(this, &staticMetaObject, 1, 0);
}


i can not use the suggested (by msdn) solution: "to use reinterpret_cast or static_cast explicitly", because i do not want to edit the moc file.



class ClassA : public QThread, public GUIWrapperClass, ...
{
...
}

where GUIWrapperClass inherits from QObject.

Is this the reason for the ambiguity? Now ClassA inherits both from QThread and GUIWrapperClass to QObject.

I HAVE TO USE GUIWrapperClass so that the ClassA works fine with our framework.

is there something one can do?

sivrisinek
30th April 2009, 17:03
I tried somthing like this, the problem is still the same...





class ThreadWrapper: public QThread
{

Q_OBJECT

public:
~ThreadWrapper();

signals:
virtual void reloadFinished(void) = 0;
virtual void stopVisualizationTimer(void) = 0;
virtual void reloadData(double requiredStartTime) = 0;

}

class ClassA : public ThreadWrapper, public GUIWrapperClass
{

signals:
void reloadFinished(void);
void stopVisualizationTimer(void);
void reloadData(double requiredStartTime);

}

sivrisinek
30th April 2009, 17:41
Compilation problem was solved using this:



class ThreadWrapper: public QThread
{

Q_OBJECT

public:
~ThreadWrapper();

signals:
void reloadFinished(void);
void stopVisualizationTimer(void);
void reloadData(double requiredStartTime);

}

class ClassA : public ThreadWrapper, public GUIWrapperClass
{

//signals:
//void reloadFinished(void);
//void stopVisualizationTimer(void);
//void reloadData(double requiredStartTime);

}