wxTimer never times out sometimes

I use the timer in one-shot mode to trigger an action after the user stops
using the GUI. As long as the user is clicking on elements in the GUI, the
timer gets retriggered (using Start). This scheme works fine most of the
time, but once in a while the event handler never gets called. After the
timer fails once, it seems to be inoperable. That is, I don't get a
timeout after performing additional actions that normally would trigger the
timer. The only way to restore correct operation is to exit the program
and restart it. My only theory is that something goes wrong if wxTimer
receives a start command at the same time that it is timing out. That is
the only scenario I can think of consistent with the sporadic nature of the
problem. Perhaps there needs to be a critical section in the code.

···

--
Jeffrey Barish

If you are using wxTimer.Start() in a thread other than the main thread,
then you need to change your code, as such is not supported on any
platform (regardless of whether it works or not on your platform). That
is, post an event to the GUI thread, that event's only job is triggering
the wxTimer.Start().

If the only thread that is executing is your single main thread, then I
doubt you are running into a race condition that requires a critical
section or lock (either in the underlying wxPython implementation or in
your code), but you may need to wait for a response from Robin to be
sure.

- Josiah

···

Jeffrey Barish <jeff_barish@earthlink.net> wrote:

I use the timer in one-shot mode to trigger an action after the user stops
using the GUI. As long as the user is clicking on elements in the GUI, the
timer gets retriggered (using Start). This scheme works fine most of the
time, but once in a while the event handler never gets called. After the
timer fails once, it seems to be inoperable. That is, I don't get a
timeout after performing additional actions that normally would trigger the
timer. The only way to restore correct operation is to exit the program
and restart it. My only theory is that something goes wrong if wxTimer
receives a start command at the same time that it is timing out. That is
the only scenario I can think of consistent with the sporadic nature of the
problem. Perhaps there needs to be a critical section in the code.

Jeffrey Barish wrote:

I use the timer in one-shot mode to trigger an action after the user stops
using the GUI. As long as the user is clicking on elements in the GUI, the
timer gets retriggered (using Start). This scheme works fine most of the
time, but once in a while the event handler never gets called. After the
timer fails once, it seems to be inoperable. That is, I don't get a
timeout after performing additional actions that normally would trigger the
timer. The only way to restore correct operation is to exit the program
and restart it. My only theory is that something goes wrong if wxTimer
receives a start command at the same time that it is timing out. That is
the only scenario I can think of consistent with the sporadic nature of the
problem. Perhaps there needs to be a critical section in the code.

A critical section would only be needed if threads are involved, but since timers are implemented as events from the platform there shouldn't be any. They are delivered like any other event.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Josiah Carlson wrote:

I use the timer in one-shot mode to trigger an action after the user
stops
using the GUI. As long as the user is clicking on elements in the GUI,
the
timer gets retriggered (using Start). This scheme works fine most of the
time, but once in a while the event handler never gets called. After the
timer fails once, it seems to be inoperable. That is, I don't get a
timeout after performing additional actions that normally would trigger
the
timer. The only way to restore correct operation is to exit the program
and restart it. My only theory is that something goes wrong if wxTimer
receives a start command at the same time that it is timing out. That is
the only scenario I can think of consistent with the sporadic nature of
the
problem. Perhaps there needs to be a critical section in the code.

If you are using wxTimer.Start() in a thread other than the main thread,
then you need to change your code, as such is not supported on any
platform (regardless of whether it works or not on your platform). That
is, post an event to the GUI thread, that event's only job is triggering
the wxTimer.Start().

If the only thread that is executing is your single main thread, then I
doubt you are running into a race condition that requires a critical
section or lock (either in the underlying wxPython implementation or in
your code), but you may need to wait for a response from Robin to be
sure.

Thanks for your comments. You raise a good point, but there is only one
thread. I was thinking that the actions that result in calls to
wxTimer.Start() happen asynchronously to the timer. Accordingly, it could
be possible that the timer is running code for dealing with actions the
timer takes at the end of the timer period at the moment it receives the
Start() call. If so, perhaps it goes into a state in which it does not
transmit the timer event and does not properly reset the timer. The
critical section would be the code that handles the timeout to be sure that
the timer does everything that needs to be done before it responds to the
new Start() call. It's also possible that I am completely wrong, but I
have no other theory for explaining why I never get a timer event
sometimes. I know that the timer was triggered because I display a static
bitmap at the same time. When the timer times out, the static bitmap
should disappear and I should see a message indicating that I made it to
the timer event handler. Neither thing happens. Also, it is not possible
to trigger the timer again.

···

Jeffrey Barish <jeff_barish@earthlink.net> wrote:

--
Jeffrey Barish

[snip]

Thanks for your comments. You raise a good point, but there is only one
thread. I was thinking that the actions that result in calls to
wxTimer.Start() happen asynchronously to the timer. Accordingly, it could
be possible that the timer is running code for dealing with actions the
timer takes at the end of the timer period at the moment it receives the
Start() call. If so, perhaps it goes into a state in which it does not
transmit the timer event and does not properly reset the timer. The
critical section would be the code that handles the timeout to be sure that
the timer does everything that needs to be done before it responds to the
new Start() call. It's also possible that I am completely wrong, but I
have no other theory for explaining why I never get a timer event
sometimes. I know that the timer was triggered because I display a static
bitmap at the same time. When the timer times out, the static bitmap
should disappear and I should see a message indicating that I made it to
the timer event handler. Neither thing happens. Also, it is not possible
to trigger the timer again.

Have you tried .Stop() then .Start()?

- Josiah

···

Jeffrey Barish <jeff_barish@earthlink.net> wrote:

Josiah Carlson wrote:

[snip]

Thanks for your comments. You raise a good point, but there is only one
thread. I was thinking that the actions that result in calls to
wxTimer.Start() happen asynchronously to the timer. Accordingly, it
could be possible that the timer is running code for dealing with actions
the timer takes at the end of the timer period at the moment it receives
the
Start() call. If so, perhaps it goes into a state in which it does not
transmit the timer event and does not properly reset the timer. The
critical section would be the code that handles the timeout to be sure
that the timer does everything that needs to be done before it responds
to the
new Start() call. It's also possible that I am completely wrong, but I
have no other theory for explaining why I never get a timer event
sometimes. I know that the timer was triggered because I display a
static
bitmap at the same time. When the timer times out, the static bitmap
should disappear and I should see a message indicating that I made it to
the timer event handler. Neither thing happens. Also, it is not
possible to trigger the timer again.

Have you tried .Stop() then .Start()?

- Josiah

I did not try it because the documentation says that "If the timer was
already running, it will be stopped by this method [start] before
restarting it." However, if you think that it might make a difference, I
will try it. At this point, I have nothing else to try, so any suggestion
is welcome.

···

Jeffrey Barish <jeff_barish@earthlink.net> wrote:

--
Jeffrey Barish

Robin Dunn wrote:

Jeffrey Barish wrote:

I use the timer in one-shot mode to trigger an action after the user
stops
using the GUI. As long as the user is clicking on elements in the GUI,
the
timer gets retriggered (using Start). This scheme works fine most of the
time, but once in a while the event handler never gets called. After the
timer fails once, it seems to be inoperable. That is, I don't get a
timeout after performing additional actions that normally would trigger
the
timer. The only way to restore correct operation is to exit the program
and restart it. My only theory is that something goes wrong if wxTimer
receives a start command at the same time that it is timing out. That is
the only scenario I can think of consistent with the sporadic nature of
the
problem. Perhaps there needs to be a critical section in the code.

A critical section would only be needed if threads are involved, but
since timers are implemented as events from the platform there shouldn't
be any. They are delivered like any other event.

That makes sense. Do you have a suggestion, then, as to why I am not
receiving an event?

···

--
Jeffrey Barish

Jeffrey Barish wrote:

Robin Dunn wrote:

Jeffrey Barish wrote:

I use the timer in one-shot mode to trigger an action after the user
stops
using the GUI. As long as the user is clicking on elements in the GUI,
the
timer gets retriggered (using Start). This scheme works fine most of the
time, but once in a while the event handler never gets called. After the
timer fails once, it seems to be inoperable. That is, I don't get a
timeout after performing additional actions that normally would trigger
the
timer. The only way to restore correct operation is to exit the program
and restart it. My only theory is that something goes wrong if wxTimer
receives a start command at the same time that it is timing out. That is
the only scenario I can think of consistent with the sporadic nature of
the
problem. Perhaps there needs to be a critical section in the code.

A critical section would only be needed if threads are involved, but
since timers are implemented as events from the platform there shouldn't
be any. They are delivered like any other event.

That makes sense. Do you have a suggestion, then, as to why I am not
receiving an event?

Unfortunately I don't.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Jeffrey Barish wrote:

Have you tried .Stop() then .Start()?

- Josiah

I did not try it because the documentation says that "If the timer was
already running, it will be stopped by this method [start] before
restarting it." However, if you think that it might make a difference, I
will try it. At this point, I have nothing else to try, so any suggestion
is welcome.

It's official: This sensible suggestion did not fix the problem.

As this is the only serious problem I have remaining in my application and
as I am stumped, I thought that a peek at some of the code might trigger
additional thoughts.

The function that I use to trigger the timer is this:

    def _startTimer(self):
        '''Utility function for starting the timer and activating the
        indicator.'''
        self.timer.Start(10000, True)
        self.ind_p.setInd()

The timeout event is bound to this:

    def doTimer(self, event):
        '''The timer timed out.'''
        print 'Timeout'
        self.ind_p.clrInd()

The _startTimer utility routine is the only place where the timer Start is
called. What I observe is that the indicator goes on but it never goes off
and I never get a message from the print statement. The fact that the
indicator went on tells me that the timer must have started, yet I never
make it to the event handler. The binding never changes. It is created
with this:

        self.Bind(wx.EVT_TIMER, self.doTimer, self.timer)

where self is the main panel.

Also, once the timer fails once, I can't find any way to trigger it again.
I keep thinking that it will trigger if I do the things that normally
trigger it and when it times out it will belatedly clear the indicator and
print the message. However, nothing I do has this effect.

I just stuck

            if self.timer.IsRunning():
                print 'Started timer'
            else:
                print 'Failed to start timer'

at the end of _startTimer. It will be interesting to see whether the timer
thinks that it is running when the indicator fails to clear.

I don't have event.Skip() at the end of doTimer. Could that be the problem?
If that's wrong, I would expect to see a problem all the time, not 1 time
out of 100. Still, maybe some memory is not getting freed, or something
like that. I'll stick it in and see what happens.

···

--
Jeffrey Barish

Jeffrey Barish wrote:

Jeffrey Barish wrote:

Have you tried .Stop() then .Start()?

- Josiah

I did not try it because the documentation says that "If the timer was
already running, it will be stopped by this method [start] before
restarting it." However, if you think that it might make a difference, I
will try it. At this point, I have nothing else to try, so any suggestion
is welcome.

It's official: This sensible suggestion did not fix the problem.

As this is the only serious problem I have remaining in my application and
as I am stumped, I thought that a peek at some of the code might trigger
additional thoughts.

The function that I use to trigger the timer is this:

    def _startTimer(self):
        '''Utility function for starting the timer and activating the
        indicator.'''
        self.timer.Start(10000, True)
        self.ind_p.setInd()

The timeout event is bound to this:

    def doTimer(self, event):
        '''The timer timed out.'''
        print 'Timeout'
        self.ind_p.clrInd()

The _startTimer utility routine is the only place where the timer Start is
called. What I observe is that the indicator goes on but it never goes off
and I never get a message from the print statement. The fact that the
indicator went on tells me that the timer must have started, yet I never
make it to the event handler. The binding never changes. It is created
with this:

        self.Bind(wx.EVT_TIMER, self.doTimer, self.timer)

where self is the main panel.

Also, once the timer fails once, I can't find any way to trigger it again. I keep thinking that it will trigger if I do the things that normally
trigger it and when it times out it will belatedly clear the indicator and
print the message. However, nothing I do has this effect.

I just stuck

            if self.timer.IsRunning():
                print 'Started timer'
            else:
                print 'Failed to start timer'

at the end of _startTimer. It will be interesting to see whether the timer
thinks that it is running when the indicator fails to clear.

I don't have event.Skip() at the end of doTimer. Could that be the problem?

It shouldn't cause any problems. The default handler doesn't do anything.

You didn't show the code that creates the timer object.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Robin Dunn wrote:

Jeffrey Barish wrote:

Jeffrey Barish wrote:

Have you tried .Stop() then .Start()?

- Josiah

I did not try it because the documentation says that "If the timer was
already running, it will be stopped by this method [start] before
restarting it." However, if you think that it might make a difference,
I
will try it. At this point, I have nothing else to try, so any
suggestion is welcome.

It's official: This sensible suggestion did not fix the problem.

As this is the only serious problem I have remaining in my application
and as I am stumped, I thought that a peek at some of the code might
trigger additional thoughts.

The function that I use to trigger the timer is this:

    def _startTimer(self):
        '''Utility function for starting the timer and activating the
        indicator.'''
        self.timer.Start(10000, True)
        self.ind_p.setInd()

The timeout event is bound to this:

    def doTimer(self, event):
        '''The timer timed out.'''
        print 'Timeout'
        self.ind_p.clrInd()

The _startTimer utility routine is the only place where the timer Start
is
called. What I observe is that the indicator goes on but it never goes
off
and I never get a message from the print statement. The fact that the
indicator went on tells me that the timer must have started, yet I never
make it to the event handler. The binding never changes. It is created
with this:

        self.Bind(wx.EVT_TIMER, self.doTimer, self.timer)

where self is the main panel.

Also, once the timer fails once, I can't find any way to trigger it
again. I keep thinking that it will trigger if I do the things that
normally trigger it and when it times out it will belatedly clear the
indicator and
print the message. However, nothing I do has this effect.

I just stuck

            if self.timer.IsRunning():
                print 'Started timer'
            else:
                print 'Failed to start timer'

at the end of _startTimer. It will be interesting to see whether the
timer thinks that it is running when the indicator fails to clear.

I don't have event.Skip() at the end of doTimer. Could that be the
problem?

It shouldn't cause any problems. The default handler doesn't do anything.

You didn't show the code that creates the timer object.

        self.timer = wx.Timer(self, wx.ID_ANY)

where self is the main panel.

···

--
Jeffrey Barish

Jeffrey Barish wrote:

Robin Dunn wrote:

Jeffrey Barish wrote:

Jeffrey Barish wrote:

Have you tried .Stop() then .Start()?

- Josiah

I did not try it because the documentation says that "If the timer was
already running, it will be stopped by this method [start] before
restarting it." However, if you think that it might make a difference,
I
will try it. At this point, I have nothing else to try, so any
suggestion is welcome.

It's official: This sensible suggestion did not fix the problem.

As this is the only serious problem I have remaining in my application
and as I am stumped, I thought that a peek at some of the code might
trigger additional thoughts.

The function that I use to trigger the timer is this:

    def _startTimer(self):
        '''Utility function for starting the timer and activating the
        indicator.'''
        self.timer.Start(10000, True)
        self.ind_p.setInd()

The timeout event is bound to this:

    def doTimer(self, event):
        '''The timer timed out.'''
        print 'Timeout'
        self.ind_p.clrInd()

The _startTimer utility routine is the only place where the timer Start
is
called. What I observe is that the indicator goes on but it never goes
off
and I never get a message from the print statement. The fact that the
indicator went on tells me that the timer must have started, yet I never
make it to the event handler. The binding never changes. It is created
with this:

        self.Bind(wx.EVT_TIMER, self.doTimer, self.timer)

where self is the main panel.

Also, once the timer fails once, I can't find any way to trigger it
again. I keep thinking that it will trigger if I do the things that
normally trigger it and when it times out it will belatedly clear the
indicator and
print the message. However, nothing I do has this effect.

I just stuck

            if self.timer.IsRunning():
                print 'Started timer'
            else:
                print 'Failed to start timer'

at the end of _startTimer. It will be interesting to see whether the
timer thinks that it is running when the indicator fails to clear.

I don't have event.Skip() at the end of doTimer. Could that be the
problem?

It shouldn't cause any problems. The default handler doesn't do anything.

You didn't show the code that creates the timer object.

        self.timer = wx.Timer(self, wx.ID_ANY)

where self is the main panel.

It's a long shot, but does using wx.Timer(self, wx.NewId()) make any difference?

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Robin Dunn wrote:

self.timer = wx.Timer(self, wx.ID_ANY)

where self is the main panel.

It's a long shot, but does using wx.Timer(self, wx.NewId()) make any
difference?

I will try it. Understand that these experiments take a long time because
the problem is sporadic.

In the meantime, I have some information from the previous test that I said
I would run. I stuck

         if self\.timer\.IsRunning\(\):
             print &#39;Started timer&#39;
         else:
             print &#39;Failed to start timer&#39;

at the end of _startTimer, right after the timer is started and the
indicator is set. The timer failed, at which point I did something that
should have retriggered the timer. I got the message "Started timer", so
the timer thinks that it is running right after I set it. I put my program
into a mode in which it ran for a long time so that I could wait to see
whether the timer ever timed out. I had not gotten a timeout message after
an hour.

And another observation: It seems that if the timer is going to fail, it
does so shortly after starting the program. However, I just started it 20
times and did not see it fail once.

I will try the experiment that you suggested now.

···

--
Jeffrey Barish