[Qt-interest] ASSERT failure in QMutex::unlock(): "A mutex must be unlocked in the same thread that locked it."
Sean Harmer
sean.harmer at maps-technology.com
Fri Jul 16 20:24:16 CEST 2010
On 16/07/2010 17:36, Sarvesh Saran wrote:
> Hi,
>
> Sorry for the poor indentation. Let me rephrase:
>
> I am simply having a tough time understanding how signals and slots work across threads.
>
> Assume that I have a MyThread:QThread object called A running and it contains a public slot setValue().
>
> //this code is in the main window
> MyThread *a = new MyThread; //create the thread
> connect(this,sendValue(int),a,setValue(int)));
>
> later in the code I emit a signal:
> emit sendValue(10);
>
> I would like to know how this emit is different from:
> a->setValue(10) ?
>
> in either case, who executes the slot setValue? Is it the MainWindow thread or MyThread?
The slot gets executed in the thread that calls a->setValue(10) and emit
sendValue(10), the main thread in your case.
This is because the QThread object has affinity with the main thread
because that is where it was created.
To ensure that your slot gets executed in the context of yoru worker
thread, you should not put the slot on the QThread object itself, but
rather create a new helper object derived from QObject (with 0 for the
parent) in the run() function of your thread class.
This new QObject will have affinity with the worker thread because that
is the context in which it was created.
So now if you make a connection between a signal from an object that has
affinity with the main thread (your mainwindow object for example) and a
slot on the new helper object in your worker thread, the default
connection mode of Qt::AutoConnection will determine that Qt should use
a queued connection for this case. [In actual fact the decision is
deferred until you emit the signal since objects can change thread
affinity with the moveToThread() call].
For your worker thread to be able to deliver the event that is used to
implement queued connections, you must ensure that you start the event
loop by calling QThread::exec() within the run() function. Without this,
your helper QObject that lives in the worker thread will not have its
slot called.
In summary, it is best to consider QThread purely as a means of
launching another thread, not as the object that does any real work in
that thread (unless you do not need the worker thread to be event driven
of course as illustrated in the Mandelbrot example). Much better to
create QObjects within the worker thread to do the work instead.
HTH,
Sean
More information about the Qt-interest-old
mailing list