Chris Weisiger wrote:
> On Fri, May 17, 2013 at 12:52 AM, Stefano Mtangoo <
mwinj...@gmail.com
> <mailto:
mwinj...@gmail.com>> wrote:
>
> Why not create it in main thread.
>
>
> As I understand it, that should be what doing wx.CallAfter() for all of
> the dialog-related calls does -- it creates an event to call the
> specified function later in the main thread.
Correct.
> The difficulty I'm running
> into is twofold:
>
> 1) I also have to use wx.CallAfter() to load my image data in the main
> thread, creating even more events, and
> 2) events don't seem to be executed in the order in which they are added
> to the event queue.
That can happen when one of the called functions does something that
will cause the pending event queue to be processed, like calling
wx.Yield. So basically what happens is that the first function is
called, and then it yields and then any pending CallAfters are called,
and then control eventually returns to the first one and it continues
running, but because the other(s) have already been run it turns out
that the first one is executed last.
>
> My loop that does this:
>
> for i, image in enumerate(images):
> wx.CallAfter(self.addImage, image)
> wx.CallAfter(statusDialog.Update, i)
>
> *should* result in the event queue alternating between "add image" and
> "update dialog" calls. In practice, however, it does all of the "add
> image" calls first, and only then does the "update dialog" calls, in
> reverse order! So the dialog shows no "progress" while all of the work
> is actually done (as I can monitor through other means), but once it is
> complete you see the progress bar instantly fill and then empty out!
Normally I recommend that people combine the two tasks into one function
and then use CallAfter just once to call that one function. However in
your case it will still likely end up with a similar problem since you
are stacking up CallAfters rather quickly. Then most likely they are
all waiting to be processed when the first one is called and if it is
still doing a yield or whatever then the others will still be processed
first.
In this case I would recommend that you don't use CallAfter for this,
but instead add your images and any other info you need to a Queue.Queue
from the worker thread and then call wx.WakeUpIdle(). In an EVT_IDLE
handler you can check if there is anything in that Queue and if there is
pull an item out and process it, update the progress dialog, call
event.RequestMore, and then return. In the next idle event you can get
the next item from the queue and take care of it. Since order is
important then I would also do something to ensure that you don't
reenter and try processing the next item while it is still processing
the prior one.
--
Robin Dunn
Software Craftsman
http://wxPython.org