Hi,
I have several files to download and a GUI to update. I know this is a
frequently asked question but i can't find an appropriate solution.
My Downloader extends threading.Thread and update a wx.Gauge in GUI
during the process.
for src in urls:
downloader = Downloader( src, destination, GUI )
downloader.start()
#work with the downloaded files...
If i don't use a downloader.join() in this for loop, I launch several
threads at the same time and so my wx.Gauge is bouncing up and down.
If i do add the downloader.join() my GUI is no more updated ( in fact,
nothing appears, it's frozen )
How can I wait the end of the thread and also be able to update the GUI
?
( I have to wait, otherwise I will work uncompleted files )
Any way to work around it?
Thanks. 9 3238
In article <11*********************@o13g2000cwo.googlegroups. com>, perchef wrote: Hi,
I have several files to download and a GUI to update. I know this is a frequently asked question but i can't find an appropriate solution. My Downloader extends threading.Thread and update a wx.Gauge in GUI during the process.
for src in urls: downloader = Downloader( src, destination, GUI ) downloader.start()
#work with the downloaded files...
If i don't use a downloader.join() in this for loop, I launch several threads at the same time and so my wx.Gauge is bouncing up and down. If i do add the downloader.join() my GUI is no more updated ( in fact, nothing appears, it's frozen ) How can I wait the end of the thread and also be able to update the GUI
Well, the constraints are this: the main thread is running the wx main loop,
and thus, cannot block by calling join on the downloader thread. Further, calling
wx from a thread other than the one running the event loop is deep voodoo and should typically
be avoided.
You need another way to pass completion information between the downloader
thread and the main thread; the simplest way is to define a custom wx
Event, and wxPostEvent from the downloader thread when it completes (
and when the gauge should be updated). wxPostEvent is safe to call from non-eventloop threads.
The main thread's wx event loop just spins, properly updating all other
parts of the GUI, and receiving events from the downloader thread.
ANother approach is to have a thread-safe Queue and have the main thread/event loop
poll the queue with queue.get_nowait() periodically (typically 0.1-1 sec).
The downloader thread shares the queue object and puts data structures (typically
class instances, strings, or ints) that indicate status updates.
The easiest approach, though, is to use the threadedselectreactor in Twisted (you need
to check the HEAD branch out with subversion, because that reactor isn't included in any releases).
With threadedselectreactor, it's easy to incorporate both the GUI event loop and the twisted reactor.
Twisted already includes lots of code for doing asynchronous callback-style IO for
IO bound processes like downloading. Further, you don't even think in an explicitly threaded way-
createing a whole thread just to manage a download process which is motly IO and a little bookkeeping is
silly. Twisted's approach just makes a lot more sense and simplifies the code too.
Dave
David E. Konerding DSD staff wrote:
[...] You need another way to pass completion information between the
downloader thread and the main thread; the simplest way is to define a custom wx Event, and wxPostEvent from the downloader thread when it completes ( and when the gauge should be updated). wxPostEvent is safe to call
from non-eventloop threads. The main thread's wx event loop just spins, properly updating all other parts of the GUI, and receiving events from the downloader thread.
ANother approach is to have a thread-safe Queue and have the main
thread/event loop poll the queue with queue.get_nowait() periodically (typically 0.1-1
sec). The downloader thread shares the queue object and puts data
structures (typically class instances, strings, or ints) that indicate status updates.
The way-cool things to transmit, in either the queue or the
event data, are tuples of:
(func, args, kwargs)
The so-called-'main' thread gets these, and blindly calls
func(*args, **kwargs). Since only the main thread can safely
update the GUI, other threads pass GUI-updating functions to be
called by the main thread.
The technique is beautifully general. The worker thread does
it's long, blocking operations independently, and when it needs
to update the GUI it sends the main thread a quick, non-blocking
function.
In wxPython, custom events can carry arbitrary data, so the easy
thing to do is just pass the (func, args, kwargs) across with
wxPostEvent (or so I've read; I'm not a wxPython user).
TkInter has no equivalent to wxPostEvent. Contrary to popular
belief, TkInter's event_generate is not thread-safe. The usual
TkInter solution is a queue, which the main thread periodically
polls via the 'after' function.
The easiest approach, though, is to use the threadedselectreactor in
Twisted (you need to check the HEAD branch out with subversion, because that reactor
isn't included in any releases). With threadedselectreactor, it's easy to incorporate both the GUI
event loop and the twisted reactor. Twisted already includes lots of code for doing asynchronous
callback-style IO for IO bound processes like downloading. Further, you don't even think
in an explicitly threaded way- createing a whole thread just to manage a download process which is
motly IO and a little bookkeeping is silly. Twisted's approach just makes a lot more sense and simplifies
the code too.
I couldn't disagree more about that being easier and simplifying
the code. "Creating a whole thread" is trivial.
--
--Bryan
David E. Konerding DSD staff wrote: Further, calling wx from a thread other than the one running the event loop is deep voodoo and should typically be avoided.
"Typically"? Let's just say "always" and maybe use the phrase "certain
to corrupt wx and crash the app" instead of "deep voodoo". :-) At least
that way the OP won't waste time experimenting...
You need another way to pass completion information between the downloader thread and the main thread; the simplest way is to define a custom wx Event, and wxPostEvent from the downloader thread when it completes ( and when the gauge should be updated). wxPostEvent is safe to call from non-eventloop threads. The main thread's wx event loop just spins, properly updating all other parts of the GUI, and receiving events from the downloader thread.
Even simpler for some purposes is wx.CallAfter(), which provides the
asynchronous performance of wxPostEvent with the "beautifully general"
approach of passing callables through a Queue which Bryan Olson
described in his post. (That is, you don't need to do polling with a
non-blocking get() on the Queue this way.)
-Peter
thanks for all these advices.
I think a custom event will be the way to go.
for the moment I use something _really_ ugly : a mix between GUI,
threads and recursive fonctions.
Peter Hansen wrote: David E. Konerding DSD staff wrote: Further, calling wx from a thread other than the one running the event loop is deep voodoo and should typically be avoided. "Typically"? Let's just say "always" and maybe use the phrase "certain to corrupt wx and crash the app" instead of "deep voodoo". :-) At least that way the OP won't waste time experimenting...
Come to think of it, wouldn't it be a good idea for a GUI
toolkit to to do something like:
import thread
# ...
def WhateverToolKitInitFunction(*args):
global _thread_of_record
_thread_of_record = thread.get_ident()
# ...
def check_thread():
if thread.get_ident() != _thread_of_record:
raise RuntimeError('Attempt to update GUI from foreign
thread.')
And then begin each non-thread-safe function like:
def SomeUpdateFunction(*args):
check_thread()
# ...
[...] Even simpler for some purposes is wx.CallAfter(),
Ah, Nice. Same method under the hood, but hides the complexity.
--
--Bryan
David E. Konerding DSD staff wrote: The easiest approach, though, is to use the threadedselectreactor in Twisted (you need to check the HEAD branch out with subversion, because that reactor isn't included in any releases). With threadedselectreactor, it's easy to incorporate both the GUI event loop and the twisted reactor. Twisted already includes lots of code for doing asynchronous callback-style IO for IO bound processes like downloading. Further, you don't even think in an explicitly threaded way- createing a whole thread just to manage a download process which is motly IO and a little bookkeeping is silly. Twisted's approach just makes a lot more sense and simplifies the code too.
Or, don't use threadedselectreactor, but instead just use normal
threading and reactor.callFromThread.
On 2005-08-10, Bryan Olson <fa*********@nowhere.org> wrote: The easiest approach, though, is to use the threadedselectreactor in Twisted (you need to check the HEAD branch out with subversion, because that reactor isn't included in any releases). With threadedselectreactor, it's easy to incorporate both the GUI event loop and the twisted reactor. Twisted already includes lots of code for doing asynchronous callback-style IO for IO bound processes like downloading. Further, you don't even think in an explicitly threaded way- createing a whole thread just to manage a download process which is motly IO and a little bookkeeping is silly. Twisted's approach just makes a lot more sense and simplifies the code too.
I couldn't disagree more about that being easier and simplifying the code. "Creating a whole thread" is trivial.
I've done both styles. Actually, I greatly prefer the single threaded approach now; conceptually,
the threaded approach is very simple, but your program ends up getting complex because the data-passing
infrastructure. And you end up structuring your logic in somewhat more convoluted ways. And
most people have such a hard time dealing with data synch between threads...
Dave
On 2005-08-10, Peter Hansen <pe***@engcorp.com> wrote: David E. Konerding DSD staff wrote: Further, calling wx from a thread other than the one running the event loop is deep voodoo and should typically be avoided. "Typically"? Let's just say "always" and maybe use the phrase "certain to corrupt wx and crash the app" instead of "deep voodoo". :-) At least that way the OP won't waste time experimenting...
Not really certain: http://wxwidgets.org/manuals/2.6.1/w...hreadfunctions
This strongly suggests you can arbitrarily grab the wx GUI lock and call GUI
functions from any thread. It's still voodoo. But we're adults here, and practicing
voodoo isn't proscribed. You need another way to pass completion information between the downloader thread and the main thread; the simplest way is to define a custom wx Event, and wxPostEvent from the downloader thread when it completes ( and when the gauge should be updated). wxPostEvent is safe to call from non-eventloop threads. The main thread's wx event loop just spins, properly updating all other parts of the GUI, and receiving events from the downloader thread.
Even simpler for some purposes is wx.CallAfter(), which provides the asynchronous performance of wxPostEvent with the "beautifully general" approach of passing callables through a Queue which Bryan Olson described in his post. (That is, you don't need to do polling with a non-blocking get() on the Queue this way.)
Very good point. I wasn't aware CallAfter had those semantics; I always used it from
the main thread. But won't wx.CallAfter cause a bit of a delay since it will wait until
all pending events are processed and only handle the function afterwards, thus inducing
an extra event loop cycle/redraw?
Dave
David E. Konerding DSD staff wrote: http://wxwidgets.org/manuals/2.6.1/w...hreadfunctions
This strongly suggests you can arbitrarily grab the wx GUI lock and call GUI functions from any thread. It's still voodoo. But we're adults here, and practicing voodoo isn't proscribed.
Oh, very nice... for my automatic testing requirements anyway. I did
not know those existed...
I agree using this in real code is probably not wise, and you're right
that it is best described as "voodoo". :)
But won't wx.CallAfter cause a bit of a delay since it will wait until all pending events are processed and only handle the function afterwards, thus inducing an extra event loop cycle/redraw?
Since it's built on PostEvent, it will do whatever happens with other
stuff that is PostEvent-ed, I suppose. Your description is probably
accurate...
-Peter This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: fooooo |
last post by:
This is a network app, written in wxPython and the socket module. This
is what I want to happen:
GUI app starts. User clicks a button to 'start' the work of the app.
When start is pressed, a new...
|
by: Zunbeltz Izaola |
last post by:
Hi,
I have the following problem.
I'm developing a GUI program (wxPython). This program has to comunicate
(TCP) whit other program that controls a laboratory machine to do a
measurement. I...
|
by: Tyler |
last post by:
Hello All:
I am currently working on a project to create an FEM model for school.
I was thinking about using wxPython to gather the 12 input variables
from the user, then, after pressing the...
|
by: Kevin Walzer |
last post by:
I'm porting a Tkinter application to wxPython and had a question about
wxPython's event loop.
The Tkinter app provides a GUI to a command-line tool. It gathers user
input, and opens an...
|
by: Benjamin |
last post by:
Hello! I am writing a search engine with wxPython as the GUI. As the
search thread returns items, it adds them to a Queue which is picked
up by the main GUI thread calling itself recursively with...
|
by: Jimmy |
last post by:
Hi, wxPython is cool and easy to use, But I ran into a problem
recently when I try to write a GUI.
The thing is I want to periodically update the content of StatixText
object, so after create...
|
by: bullockbefriending bard |
last post by:
I am a complete ignoramus and newbie when it comes to designing and
coding networked clients (or servers for that matter). I have a copy
of Goerzen (Foundations of Python Network Programming) and...
|
by: mistersulu |
last post by:
Hi all:
I'm using a wx.ListView object with a multi-threaded wxPython app.
The list is dynamically generated and accessed across two or more
threads. In spite of the fact that I have checks to...
|
by: Stef Mientki |
last post by:
Peter Anderson wrote:
In PyScripter, you should run wxPython in the plain remote machine (not
the wxPython remote),
and you should set "reset before run flag" or reset the remote machine
each...
|
by: Faith0G |
last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
|
by: ryjfgjl |
last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
|
by: Charles Arthur |
last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
|
by: aa123db |
last post by:
Variable and constants
Use var or let for variables and const fror constants.
Var foo ='bar';
Let foo ='bar';const baz ='bar';
Functions
function $name$ ($parameters$) {
}
...
|
by: ryjfgjl |
last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
|
by: ryjfgjl |
last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
|
by: nemocccc |
last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
|
by: Sonnysonu |
last post by:
This is the data of csv file
1 2 3
1 2 3
1 2 3
1 2 3
2 3
2 3
3
the lengths should be different i have to store the data by column-wise with in the specific length.
suppose the i have to...
|
by: Hystou |
last post by:
There are some requirements for setting up RAID:
1. The motherboard and BIOS support RAID configuration.
2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
| |