[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