[Interest] QEventLoop -- not sure I am correctly using this
Jason Kretzer
Jason at gocodigo.com
Mon Dec 2 22:47:22 CET 2013
Thanks for the information! Very helpful!
Here is the BackgroundTaskManager full constructor — since you brought up the idea of parentage — I thought this might be helpful to the conversation.
BackgroundTaskManager::BackgroundTaskManager(QObject *parent) :
QObject(parent)
{
QTimer* timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(runTasks()));
timer->start(300000); //fiveminutes
thread = new QThread();
this->moveToThread(thread);
thread->start();
}
BackgroundTaskManager::~BackgroundTaskManager() {
thread->deleteLater();
_instance->deleteLater();
}
void BackgroundTaskManager::init()
{
qDebug() << "Starting Background Task Manager";
_instance = new BackgroundTaskManager();
}
BackgroundTaskManager* BackgroundTaskManager::instance()
{
if (_instance == 0) {
init();
}
return _instance;
}
As I am not sure what would be important to this, I am including more information.
In the header, here are the corresponding prototypes:
public:
static BackgroundTaskManager* instance();
static void init();
private:
explicit BackgroundTaskManager(QObject *parent = 0);
Basically, in main the class is instantiated like this.
BackgroundTaskManager::init();
Then if it is needed, it can be referred to as BackgroundTaskManager::instance(); for instance for connecting slots/signals.
I didn’t design the class, I am just using it. :) However, I am not averse to rewriting the thing! Here is what the purpose CURRENTLY is. Every 5 minutes the runTasks method is supposed to run in the background. If during these tasks, a change is needed in the main thread, a signal is emitted. The connections are set up in the main thread. As an example, inside the player object constructor I mentioned earlier.
connect(BackgroundTaskManager::instance(), SIGNAL(firstTaskCompleted()), this, SLOT(restartPlayer()));
The point is that the tasks get run by the BackgroundTaskManager without blocking the player doing its thing.
Is the above the way to go about it?
-----------------------
Regarding the QEventLoop:
I am definitely going to switch out to a different method for the 1 second timer that I mentioned before. Just call a method with a Qtimer that fires a function every second. Then set up a connection to the quit slot for the timer when circumstances warrant that it quit — i.e. when the taskQueue is empty.
-Jason
- - - - - - - - - - - - - - - - - - - - - - -
Jason R. Kretzer
Application Developer
Google # 606-887-9011
Cell # 606-792-0079
Jason at gocodigo.com<mailto:Jason at gocodigo.com>
“quidquid latine dictum sit altum videtur”
[cid:image001.png at 01CECA4D.CA4030A0]
On Dec 2, 2013, at 3:29 PM, <andre at familiesomers.nl<mailto:andre at familiesomers.nl>> <andre at familiesomers.nl<mailto:andre at familiesomers.nl>> wrote:
Hi,
It looks to me, that you're indeed doing it wrong. It seems you're
trying to let your backgroundtaskmanager both manage a thread and be
_in_ that thread. That is not the way to go. I'd separate the two
issues. If you want the backgroundTaskManager to run in it's own thread,
then either just make it a "front" for a backend implementation that you
move to a thread managed by backgroundTaskManager, or just let let the
whole backgroundTaskManager be unconcerned with what thread it runs in,
and have whoever creates/owns/manages it be responsible for moving it to
a separate thread if that is desirable.
Then about your use of QEventLoop: no, I'd not use it this way.
QEventLoop is not meant as an escape to 'pause' execution of your
method. If you want to wait for about a minute, why not use a QTimer
directly? I don't see a need for QEventLoop here at all.
As to why your setup doesn't work and your eventloop seems blocked
during your background task: I guess you gave your BackgroundTaskManager
a parent object? That won't work. A whole parent/child tree must live in
the same thread. So, I guess your BackgroundTaskManager did not actually
get moved to the thread at all.
André
Jason Kretzer schreef op 02.12.2013 20:27:
Maybe that last bit would be a bit more clear.
The first qDebug statement writes out — I have it set to give the
time when it is written as well — but the qDebug does not write
until after the heavy task is completed in backgroundtaskmanager. Any
other time, this performs as expected, ticking along every second.
-Jason
_- - - - - - - - - - - - - - - - - - - - - - -_
_JASON R. __KRETZER_
_ _
_APPLICATION DEVELOPER_
_Google # 606-887-9011_
_Cell # 606-792-0079_
_Jason at gocodigo.com<mailto:Jason at gocodigo.com>_
_ _
_“QUIDQUID LATINE DICTUM SIT ALTUM VIDETUR”_
_ _
On Dec 2, 2013, at 2:14 PM, Jason Kretzer <Jason at gocodigo.com<mailto:Jason at gocodigo.com>> wrote:
Good Day,
I have in my application, two classes. When the application starts
up, one of the classes -backgroundtaskmanager - gets instantiated.
In the constructor, a QTimer is started to timeout every 5 minutes
and call runTasks. The instantiation is then moved to a separate
thread so that it can run without impacting the rest of the
application.
Here are the contents of the constructor.
QTimer* timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(runTasks()));
timer->start(300000); //fiveminutes
thread = new QThread();
this->moveToThread(thread);
thread->start();
The second class -player- is instantiated in the main thread. Once
it is instantiated, it begins doing other tasks. Basically, a method
is called with the following code. This code is designed to make the
while loop delay for one second before executing the rest of the
loop (one second-ish, I know it is not perfect but it has good
enough resolution for what I need).
while(!taskQueue.isEmpty()) {
qDebug() << “BEFORE QEVENTLOOP”;
QEventLoop wait1Sec;
QTimer::singleShot(1000, &wait1Sec,SLOT(quit()));
wait1Sec.exec();
aDebug() << “AFTER QEVENTLOOP”;
QList<Task*> instances;
for(int t=seconds; t>previousTime; t—) {
QList<Task*> vals = taskQueue.values(t);
while(!vals.isEmpty()) {
instances.insert(0, vals.takeLast());
}
taskQueue.remove(t);
}
previousTime = seconds;
miliSeconds = QDateTime::currentMSecsSinceEpoch() -
today.toMSecsSinceEpoch();
seconds = miliSeconds/1000;
}
NOTE: the two sets of tasks these do are not related.
So, anyway, every 5 minutes the tasks in backgroundtaskmanager are
run. Some of these tasks can take up to a minute. When the
backgroundtaskmanager class runs a task that does take this long
(remember it is in a separate thread), the player class code above
gets hung in what appears to be the inside of the QEventLoop. The
qDebug statements don’t write out until the tasks in the
backgroundtaskmanager are finished. Then it rushes through to catch
up.
My question is, am I correctly doing this at all? Is this the proper
use of a QEventLoop?
Thanks!
-Jason
_- - - - - - - - - - - - - - - - - - - - - - -_
_JASON R. __KRETZER_
_ _
_APPLICATION DEVELOPER_
_Google # 606-887-9011_
_Cell # 606-792-0079_
_Jason at gocodigo.com<mailto:Jason at gocodigo.com>_
_ _
_“QUIDQUID LATINE DICTUM SIT ALTUM VIDETUR”_
_ _
<image001.png>
_______________________________________________
Interest mailing list
Interest at qt-project.org<mailto:Interest at qt-project.org>
http://lists.qt-project.org/mailman/listinfo/interest
_______________________________________________
Interest mailing list
Interest at qt-project.org<mailto:Interest at qt-project.org>
http://lists.qt-project.org/mailman/listinfo/interest
_______________________________________________
Interest mailing list
Interest at qt-project.org<mailto:Interest at qt-project.org>
http://lists.qt-project.org/mailman/listinfo/interest
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20131202/47285557/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: image001.png
Type: image/png
Size: 13452 bytes
Desc: image001.png
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20131202/47285557/attachment.png>
More information about the Interest
mailing list