[Interest] Threading Question
Constantin Makshin
cmakshin at gmail.com
Sat Oct 11 16:04:56 CEST 2014
You're right, but the original Jason's message contains this fragment:
> Inside of BackgroundClass in the constructor, I start a QTimer that is supposed to go off every 5minutes and call the runTasks function when it does.
> QTimer* timer = new QTimer(this);
So the timer is created on the heap as a child of BackgroundClass object
and therefore will/should be moved along with that object.
On 10/10/2014 08:48 PM, Alan Ezust wrote:
> From what I understand, moveToThread() requires a parent-child
> relationship between the objects for the "subtree" to include them.
>
> If the QTimer was a subobject (data member) rather than a pointer to
> another heap object with the parent set, then the QTimer won't be moved
> to the other thread along with the containing object (!). Certain
> complex Qt objects can't moved properly to another thread because of
> this reason.
>
>
>
> On Thu, Oct 9, 2014 at 8:01 AM, Constantin Makshin <cmakshin at gmail.com
> <mailto:cmakshin at gmail.com>> wrote:
>
> The description of QObject::moveToThread() says the whole object's
> "subtree" is moved, so that hypothesis doesn't sound very plausible.
>
> On Oct 9, 2014 3:06 PM, "Jason Kretzer" <Jason at gocodigo.com
> <mailto:Jason at gocodigo.com>> wrote:
>
> Ack! You are correct.
>
> I guess I would do something like this to remedy that:
>
> in the main:
> BackgroundTaskManager::init();
> QThread *thread = new QThread();
> connect(thread, SIGNAL(started()),
> BackgroundTaskManager::instance(), SLOT(startTimer()));
> BackgroundTaskManager::instance()->moveToThread(thread);
> thread->start();
>
> where the SLOT startTimer would instantiate that QTimer that was
> previously in the constructor.
>
> correct?
>
> -Jason
>
> On Oct 9, 2014, at 6:46 AM,
> interest-bounces+jason=gocodigo.com at qt-project.org
> <mailto:gocodigo.com at qt-project.org> wrote:
>
> >
> > On Thursday 09 October 2014 03:32:20 Jason Kretzer wrote:
> >> Thanks for the response.
> >>
> >> Yeah, I have placed qDebug() just before and just after the emit. The one
> >> before always prints, the one after never does except in the following
> >> case. If I change the connection to QueuedConnection, then the qDebug
> >> right after does print, the rest of the function does return and the next
> >> iteration of the while loop does start. However, in the slot, as soon as
> >> it starts to execute, the loop literally stops executing at another spot.
> >> This leads to the same condition, the mutex is never released.
> >>
> >> The idea is that the BackgroundClass just be executing on its own while the
> >> main thread (Thread A) is off doing what it does.
> >>
> >> Is it possible that the program flow of BackgroundClass is being pulled back
> >> into the main thread when the slot starts executing and is thus waiting its
> >> turn?
> >>
> >> -Jason
> >>
> >> On Oct 9, 2014, at 12:11 AM, interest-bounces+jason=gocodigo.com at qt-
> > project.org <http://project.org> wrote:
> >>> Two suggestions:
> >>> 1) add qDebug-s around the "emit someSignal();" line to see whether it
> >>> returns or not, hanging somewhere in validateResult();
> >>> 2) try to explicitly specify the Qt::QueuedConnection type for the
> >>> someSignal() connection — if it helps, then the [most likely] cause is
> >>> Qt choosing wrong connection type.
> >>>
> >>> And, as always, a minimal compilable example would be nice. :)
> >>>
> >>> On 10/09/2014 07:53 AM, Jason Kretzer wrote:
> >>>> Addendum at the bottom…
> >>>>
> >>>> On Oct 8, 2014, at 11:42 PM, Jason Kretzer <Jason at gocodigo.com <mailto:Jason at gocodigo.com>> wrote:
> >>>>> I am a bit confused on threading.
> >>>>>
> >>>>> Lets say I have Thread A — which is where the program is started — has
> >>>>> main(), etc.
> >>>>>
> >>>>> Inside of main() I instantiate a class called BackgroundClass and I move
> >>>>> it to another thread (Thread B).>>>
> >>>>> BackgroundClass::init();
> >>>>>
> >>>>> QThread *thread = new QThread();
> >>>>> BackgroundClass::instance()->moveToThread(thread);
> >>>>> thread->start();
> >>>>>
> >>>>> Inside of BackgroundClass in the constructor, I start a QTimer that is
> >>>>> supposed to go off every 5minutes and call the runTasks function when
> >>>>> it does. QTimer* timer = new QTimer(this);
> >
> > And in _which_ thread does this happen? I would guess the constructor is
> > running in the main thread. So you create the timer there, too.
> > Later you move your BackgroundClass to the other thread, but the timer stays
> > where it was created.
> >
> >>>>>
> >>>>> connect(timer, SIGNAL(timeout()), this, SLOT(runTasks()));
> >>>>> timer->start(FIVE_MINS);
> >>>>>
> >>>>> I put a qDebug in the runTasks function to ensure that it is a different
> >>>>> thread than the main thread (Thread A). qDebug() << "Running tasks...
> >>>>> -- Thread ID: " << QThread::currentThreadId(); //inside runTasks
> >>>>>
> >>>>> This always shows a different ID than the main thread.
> >>>>>
> >>>>>
> >>>>> Back in the main thread (Thread A), I instantiate another class AFTER
> >>>>> the BackgroundClass instantiation.
> >>>>>
> >>>>> WorkManager::init();
> >>>>>
> >>>>> this is not moved to a separate thread so, I assume it stays in Thread
> >>>>> A.
> >>>>>
> >>>>> In the constructor of WorkManager, I connect Signals from
> >>>>> BackgroundClass to Slots in WorkManager like so.
> >>>>>
> >>>>> connect(BackgroundTaskManager::instance(), SIGNAL(someSignal()),
> >>>>> instance(), SLOT(restartWorker()));
> >>>>>
> >>>>> When the BackgroundClass finishes a task, it emits the someSignal.
> >>>>>
> >>>>>> From what I can tell, as soon as the someSignal is emitted, the
> >>>>>> restartWorker slot is called and the rest of the code that is
> >>>>>> immediately after that does not execute. For example, above, the
> >>>>>> runTasks function is supposed to run several tasks in a while loop.
> >>>>>> To make sure this loop is thread safe, so it can be the only thing
> >>>>>> running those tasks I put a mutex around the while loop. At the end
> >>>>>> of the runTask function, the someSignal is emitted the result is set,
> >>>>>> and then it is returned.>>>
> >>>>> if (!mutex.tryLock()) {
> >>>>>
> >>>>> qDebug() << "Previous instance of RunTasks still running...";
> >>>>> return;
> >>>>>
> >>>>> }
> >>>>>
> >>>>> while(moreTasks) {
> >>>>>
> >>>>> bool result = runTask(t);
> >>>>>
> >>>>> updateDatabase(t, result);
> >>>>>
> >>>>> }
> >>>>> mutex.unlock();
> >>>>>
> >>>>>
> >>>>> Unforturnately, the runTask method never returns, it appears that the
> >>>>> restartWorker is called immediately upon someSignal being emitted.
> >>>>>
> >>>>> So, I say all that to ask, why does the rest of the code not execute?
> >>>>> Obviously, I am doing something wrong, but I am not sure where the flaw
> >>>>> is. Would anyone be so kind as to point me in the right direction?>>
> >>>> ADDENDUM:
> >>>> Since the runTask method never returns, the mutex is never released. So,
> >>>> it stalls because the mutext is not released.
> >>>>
> >>>> Also, just to clarify, the end of runTask, looks like this:
> >>>> …
> >>>> ...
> >>>> emit someSignal();
> >>>> result = validateResult(); //last second validation
> >>>> return result;
> >>>> }
> >>>>
> >>>>
> >>>> -Jason
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20141011/880eb681/attachment.sig>
More information about the Interest
mailing list