[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-devel
Subject:    Re: Multi-threaded programming involving the GUI thread?
From:       Robert Knight <robertknight () gmail ! com>
Date:       2010-01-08 10:24:51
Message-ID: 13ed09c01001080224t78ed67f3ud12b5cfb15d2a4bd () mail ! gmail ! com
[Download RAW message or body]

> In KDE3 Gwenview I had few places where a worker thread needed a little thing
> to be done in the UI thread, in the middle of the work of course. I created
> for it what I believe Qt4 has as Qt::BlockingQueuedConnection (I haven't
> tried it).

This approach can be used but you need to be careful about blocking
signal emissions from a worker thread to the main thread because
you can easily end up with a deadlock when the application shuts down
if the main thread waits
for the worker job/thread to finish whilst the worker is waiting for a
response to a signal from
the main thread.

As far as I know, Qt::BlockingQueuedConnection does not provide a way
to cancel the call once it is
in-flight.

There are several options I can think of to avoid the problem.

1.  Use asynchronous calls from the worker to the main thread and add
a slot in the worker
which is called when the main thread has performed the task that the
worker needs doing.
This is the message passing concept implemented using signals and slots in Qt.

2.  Seperate the background task into a pipeline of sub-tasks, with
any work that needs to be done by the main thread
being done between sub-tasks.

3.  Re-implement the Qt::BlockingQueuedConnection concept in a way
that allows the main thread to cancel any pending
calls from the worker.  This can be using a semaphore for example.
The worker makes a call to the main thread (using
QMetaObject::invokeMethod() for example) and passes a pointer to a
semaphore as an argument.  The semaphore is also
registered in a collection somewhere.  The worker emits an
asynchronous signal and then waits on the semaphore.
When the work has been done by the main thread, it releases the
semaphore.  Alternatively if the program shuts down
whilst the worker is active, it can release all the semaphores in the
worker's collection.

You also need to bear in mind that any points in the worker where it
is waiting for the main thread to do some work can
add quite a bit to the total time for the operation because of the
round-trip delay when sending messages between threads.

Regards,
Robert.

2010/1/7 Lubos Lunak <l.lunak@suse.cz>:
> On Thursday 07 of January 2010, Stefan Majewsky wrote:
>> Am Donnerstag, 7. Januar 2010 00:14:23 schrieb Aaron J. Seigo:
>> > as an aside, do you need to operate on QPixmaps, or can you get away with
>> > QImage? because you can do QImage ops in a separate thread.
>>
>> That's the simple solution, but I need both forms. I use the QImage data
>> for creating the shadows (QGraphicsDropShadowEffect won't work because of
>> missing API), but I also need to fill the graphics into
>> QGraphicsPixmapItems. (And I suppose there are no QGraphicsImageItems for a
>> reason.) The tricky thing is that the QPixmap handling might/could/will
>> also happen inbetween other jobs that can be run in worker threads.
>
>  In KDE3 Gwenview I had few places where a worker thread needed a little thing
> to be done in the UI thread, in the middle of the work of course. I created
> for it what I believe Qt4 has as Qt::BlockingQueuedConnection (I haven't
> tried it). Connect a signal to a slot in the UI thread, pass data as
> references/pointers, emit with data from the worker thread, do the work in
> the slot, pass data back using the arguments too. Because of the blocking you
> don't even need to care there are threads involved, with a small wrapper
> function it might not even be noticeable :). Worked fine in KDE3, hopefully
> works with Qt4 too.
>
> --
>  Lubos Lunak
>  openSUSE Boosters team, KDE developer
>  l.lunak@suse.cz , l.lunak@kde.org
>
>>> Visit http://mail.kde.org/mailman/listinfo/kde-devel#unsub to unsubscribe <<
>
 
>> Visit http://mail.kde.org/mailman/listinfo/kde-devel#unsub to unsubscribe <<

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic