Simple question - if you call wx.CallAfter more than once before returning
control back to MainLoop, are the events guaranteed to be triggered in the
same sequence that they are called, or not necessarily?
I would have assumed that the answer is yes, but I am getting some bizarre
inconsistency which could be explained if the answer is no.
Not necessarily. The only guarantee with wx.CallAfter is that the
function passed will be executed in the GUI thread, sometime after the
call to wx.CallAfter. Implementation-wise, it just creates an event
(and event handler if one doesn't already exist), and posts it to the
application.
If you need for the calls to be sequential, you may want to consider
using something like the following, which does guarantee function
calling order (at least with a single-threaded application)...
handling = 0
to_handle =
def handleCalls():
global handling
while to_handle:
fcn, args, kwargs = to_handle.pop(0)
fcn(*args, **kwargs)
handling = 0
def CallAfter(fcn, *args, **kwargs):
global handling
to_handle.append((fcn, args, kwargs))
if not handling:
handling = 1
wx.CallAfter(handleCalls)
- Josiah
···
"Frank Millman" <frank@chagford.com> wrote:
Simple question - if you call wx.CallAfter more than once before returning
control back to MainLoop, are the events guaranteed to be triggered in the
same sequence that they are called, or not necessarily?
I would have assumed that the answer is yes, but I am getting some bizarre
inconsistency which could be explained if the answer is no.
> Simple question - if you call wx.CallAfter more than once before
> returning control back to MainLoop, are the events guaranteed to be
> triggered in the same sequence that they are called, or not
necessarily?
>
> I would have assumed that the answer is yes, but I am getting some
> bizarre inconsistency which could be explained if the answer is no.
Not necessarily. The only guarantee with wx.CallAfter is
that the function passed will be executed in the GUI thread,
sometime after the call to wx.CallAfter.
Implementation-wise, it just creates an event (and event
handler if one doesn't already exist), and posts it to the
application.
Thanks for the info, Josiah.
It turns out that my code is not stable anyway, so I will have to refactor
it in such a way that this question does not arise.
I was doing this (pseudocode) -
create Frame, ending with wx.CallAfter(firstCtrlOnFrame,SetFocus)
followed by frame.Show()
create Dialog, ending with wx.CallAfter(firstCtrlOnDlg,SetFocus)
followed by dlg.ShowModal()
I won't bore you with the details - it gets a bit gory - but on GTK2 I found
that, depending on other factors, I could not guarantee which of the
controls would fire its EVT_SET_FOCUS first.
The whole thing needs a rethink, but at least you confirmed that I am not
going mad :-}
Simple question - if you call wx.CallAfter more than once before returning
control back to MainLoop, are the events guaranteed to be triggered in the
same sequence that they are called, or not necessarily?
The events created by wx.CallAfter are added to a pending event queue, and during the next idle time the events are pulled from the queue and dispatched. So normally they should happen in the same order that wx.CallAfter is called, but as each event is dispatched and the functions are called, they could result in other events happening and being dispatched or queued, or there could be wx.Yield calls that nest another pass through the idle handlers, so the perceived order of execution can potentially be turned around and flipped inside out.
···
--
Robin Dunn
Software Craftsman http://wxPython.org Java give you jitters? Relax with wxPython!
create Frame, ending with wx.CallAfter(firstCtrlOnFrame,SetFocus)
followed by frame.Show()
create Dialog, ending with wx.CallAfter(firstCtrlOnDlg,SetFocus)
followed by dlg.ShowModal()
I won't bore you with the details - it gets a bit gory - but on GTK2 I found
that, depending on other factors, I could not guarantee which of the
controls would fire its EVT_SET_FOCUS first.
I beleive the problem is not wxCallAfter - it cannot mix-up the sequence itself. But you trying to use it for handing very tricky part - focus handling. Suppose that some of your widgets have his own idea about focus handling. Then there is a race condition between your just created/displayed widgets and your "focus moving" code.
> I was doing this (pseudocode) -
>
> create Frame, ending with wx.CallAfter(firstCtrlOnFrame,SetFocus)
> followed by frame.Show()
> create Dialog, ending with wx.CallAfter(firstCtrlOnDlg,SetFocus)
> followed by dlg.ShowModal()
>
> I won't bore you with the details - it gets a bit gory -
but on GTK2 I
> found that, depending on other factors, I could not
guarantee which of
> the controls would fire its EVT_SET_FOCUS first.
I beleive the problem is not wxCallAfter - it cannot mix-up
the sequence itself. But you trying to use it for handing
very tricky part - focus handling. Suppose that some of your
widgets have his own idea about focus handling. Then there is
a race condition between your just created/displayed widgets
and your "focus moving" code.
Vladimir Ignatov
Thanks for the reply, Vladimir. You are right, the whole idea is inherently
unstable.
My intention was that Frame is the main application frame, but under certain
circumstances I need to call Dialog to prompt for some information before
the frame starts. Depending on the response, it could result in the frame
being closed straight away.
I have now changed the sequence of events. If I need to prompt for
information, I call the same screen, but as a Frame in its own right, before
calling the main application frame. I then close the frame, and if I do not
want the main frame to run, I do not call it at all.
It required a bit of reorganisation of my app, but it works much more stably
now. There is a small cosmetic difference. With my original method, the main
frame was visible before I called the dialog, which gave a 'context' to the
user. My new method does not have this benefit. However, I can live with
that.