[PyQt] Cross-thread signal connections

Jason Voegele jason at jvoegele.com
Fri Aug 22 19:29:06 BST 2008

Hi all,

I am embarking upon my first PyQt application and I've come across an 
issue using cross-thread signal connections that I can't figure out, 
and I'm hoping someone here can help me.

The application I'm working on consists of several long-running tasks 
that I would like to have execute in the background without freezing 
the GUI, and furthermore I would like to execute several tasks 
concurrently.  Therefore I have created a Task class to represent the 
tasks, and an Executor class which manages executing the tasks in a 
dynamically determined number of threads [1].  Task objects emit 
signals for state changes (such as RUNNING, CANCELED, etc.) and also to 
report progress.

The way I use these Tasks in my application is as follows:

1) Main (GUI) thread creates a bunch of Task objects.
2) Main thread connects signals of Task objects to slots of various 
objects that live in the main thread.
3) Main thread submits each task to an Executor.
4) Executor creates a few threads.  Each thread takes a Task, executes 
it, and repeats until all Tasks have been executed.
5) As each Task is executing, it will emit its state change and progress 
signals.  Since the Task is executing in a background thread, its 
signals are emitted from that thread.

Now the problem is that the main (GUI) thread is never receiving the 
signals from the Tasks that are executing in the background threads.  I 
know that cross-thread signals require an event loop in the receiver, 
and that of course is the case here.  I think the problem is that the 
signal/slot connections are made in the main thread in (2), but that 
the signals are not emitted from the same thread in which the 
signal/slot connections were made.  It seems like once the Task is 
executing in a separate thread, its existing signal/slot connections 
are lost, or at least do not apply in the new thread.  I've tried it 
both with and without calling moveToThread on the Task object, and it 
doesn't seem to make a difference.

Unfortunately, at the time when my application is creating the Task 
objects and connecting to its signals, it has no idea what thread the 
task will end up executing in.

Does anyone have any advice on how to make this scheme work?  Thanks for 
any help you can offer.

[1] This scheme is similar to the facilities offered by the new 
QtConcurrent module, but since that module is not yet available in PyQt 
I cannot use it.  I also have other reasons not to use QtConcurrent for 
this particular application, but I won't go into the details here.

Jason Voegele
The aim of science is to seek the simplest explanations of complex
facts.  Seek simplicity and distrust it.
		-- Whitehead.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: This is a digitally signed message part.
Url : http://www.riverbankcomputing.com/pipermail/pyqt/attachments/20080822/187c3914/attachment.bin

More information about the PyQt mailing list