Hi Oliver,
Finally, I found some time to give you feedback on your previous
email. I read your article with great attention and my situation is
in fact case 2. in your article. I have a main thread that runs the
complete GUI and I launch (for the time being still) batch files in a
second thread.
Those batch files are generating output and it's that output I want to
"send back" to my main thread to update one or more of the fields of
the GUI. And for this, I'm currently using PyPubSub 1.0.
So, I'm registering/subscribing in the main thread to notifications
that come from the PyPubSub module. In the sub thread, I'm sending
information/notifications to the PyPubSub module, which distributes
the stuff. Well, you know it a trillion times better than me how it
works...
However, while the sub thread can have data available that, via
PyPubSub, is send to the main thread to update the GUI, also the main
thread can have data to update the GUI (the main and sub thread can
even have data for the same widgets).
And as far as Qt is concerned, you should not update the GUI from
different threads. Hence, using PyPubSub 1.0 gives me troubles since
both main and sub thread are updating the same widget(s) at the
(possible) same time. That's indeed asking for trouble...
I also know that, when you use the QtSignal() functionality, you can
emit (submit) signals from one module to another. In the book "Rapid
GUI Programming with PyQt", there's a chapter about multithreading.
I've attached 2 pages of that book which nicely explain what happens
if one thread is sending information to the other using the PyQt
signal mechanism. "Automagically", the data sent from one thread to
the other is decoupled and put in the main thread that contains the
event loop of the GUI.
The following snippet of the document is very important:
"
Behind
the scenes, when cross-thread signals are emitted, instead of calling
the relevant
method directly as is done for signals emitted and received in the
same
thread, PyQt puts an event onto the receiving thread’s event queue
with any
data that was passed. When the receiver’s event loop gets around to
reading
the event, it responds to it by calling the relevant method with any
data that
was passed.
"
This way, the sub thread cannot "directly" call methods from the main
thread, it has to "attach" its message to the main event loop.
That also avoids the problems I'm currently having, being two threads
who want to "claim" widgets to be updated at the same time.
So, very "simplymatic" said: my idea was to replace your "sendmessage"
with the PyQt's QSignal, to "automagically" decouple the sub thread
call from the main thread with respect to updating the GUI widgets.
Now back to your article:
Your case 2. requires a kind of "polling" on a queue. I didn't do
this yet in Python (as I am quite new to both Python as well as PyQt),
but I can imagine that this is not the most resource-efficient
method. Next to this, you also have to introduce a queue (which I
also haven't done yet in PyQt).
Since you're very much authored in Python, how would you exactly do
this? Your article shows pseudo code, but it would be nice if a "real
life" example could be given.
Anyhow, I think if you would be willing to introduce PyQt (or
wxPython) into your PyPubSub module (version 3), you could resolve
this in an easy way without having to have the hassle described just
above.
Again, maybe I see it way too simple, but introducing QtSignals where
you currently do the callbacks, would solve the multithreading problem
in an elegant way, since this is all done by the PyQt package (in case
of using QtSignal). Don't know, however, if such mechanism also
exists in wxPython.
Hope the above makes sense...
Best rgds,
--Geert