[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