Categories: Python | S60 | Code Examples | How To
This page was last modified 13:46, 13 June 2008.
How to Not to use Timers
From Forum Nokia Wiki
I've tried to use timers for animation with limited, but not complete, success. Small sample code was easy, but 16 Puzzle v3.0 is now 800+ lines of code. Somehow moving from simple Timer cases to more complex ones wasn't easy at all, something went wrong all the time!
Here I have documented seven (7) different errors you can make with Timer, how to identify each and fix them. There's a few correct ways, too, I hope.
My experiments continue, but it's beginning to look better. In general I very strongly propose not to both use asynchronous and synchronous timers in same application. More exactly I very strongly propose using only async timers (the ones with callback function). That might require a bit more complex application logic, but life with timers is much easier. Not to mention you have a possibility to save battery.
Usage: press keyboard numbers 1, 2, 3, 4 and 5.
# # Timer Sample # # I went through most possible errors anyone can do with Timers. # After all the trouble I want to demonstrate how timers can be # used and how to identify some of the mistakes. Hope it helps! # # Copyright (c) 2008 Jouni Miettunen # http://jouni.miettunen.googlepages.com/ # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import e32 import appuifw import key_codes import random g_count = 0 g_limit = 3 # You can use just one timer for whole program # Just ALWAYS remember to cancel it before use my_timer = e32.Ao_timer() # Not a timer, but close (Active Object) relative app_lock = e32.Ao_lock() def get_color(): ''' Generate random RGB color, used to proof that something happens ''' return (random.choice(range(0,255)), random.choice(range(0,255)), random.choice(range(0,255))) def timer_color1(): ''' Timer callback without parameters ''' global g_count if g_count < g_limit: g_count += 1 else: g_count = 0 return # Change screen color, show that something happens canvas.clear(get_color()) # You might call this routine before timer has expired # Solution: always cancel timer beforehands my_timer.cancel() # Note: Timer interval is in SECONDS my_timer.after(1, timer_color1) # Watch closely and see pattern: color change + dialog # Program execution continued immediately after timer set # Timer trickers callback function after given interval appuifw.note(unicode('Count: ' + str(g_count))) # Screen goes white, because we're missing redraw callback # Dialog removal requests screen update --> blank by default # Not a defect as itself, redraw is missing on purpose # Error: # Python: System error (-50) # TypeError: bad argument type for built-in operation # Solution: # Add time interval (SECONDS) # This is invalid sample code, do not use: # my_timer.after(timer_color1) def timer_color2(a_color=(0, 0, 0)): ''' Timer callback with parameters ''' global g_count if g_count < g_limit: g_count += 1 else: g_count = 0 return # If no color was given (EKeyRightArrow) then it's default (now BLACK) # Otherwise given color is used, see end of this function canvas.clear(a_color) # You might call this before timer has expired # Solution: always cancel timer beforehands my_timer.cancel() # If you want to give parameters to callback # you MUST use lambda == standard python expression # Note: Timer interval is in SECONDS my_timer.after(0.5, lambda:timer_color2(get_color())) # Error: # Python: System error (-50) # TypeError: callable expected for 2nd argument # Solution: # Use lambda when callback has parameters # This is invalid sample code, do not use: # my_timer.after(0.5, timer_color2(get_color())) # Error: # Python: System error (-50) # RuntimeError: maximum recursion depth exceeded # Reason: # Your timer callback called itself in loop too many times # Most likely because of invalid callback setup # Solution: # Use something to limit and break recursion # Check your code # This is invalid sample code, do not use: # my_timer.after(0.01, timer_color2(get_color())) def timer_crash3(): ''' Sample how to crash without timer.cancel ''' canvas.clear(get_color()) # Error: # Python: System error (-50) # RunTimerError: Timer pending - cancel first # Reason: # Crash if you call this before timer has expired # Missing cancel on active timer # Solution: # add my_timer.cancel() just before my_timer.after() # Note: # Everything is ok, IF you call this AFTER timer has expired # Always cancel timer beforehands, just in case my_timer.after(2, timer_crash3) def timer_color4(): ''' Blocking timer sample ''' # Change screen color, show that something happens canvas.clear(get_color()) # You might call this before timer has expired # Solution: always cancel timer beforehands my_timer.cancel() # Note: Timer interval is in SECONDS #my_timer.after(2, timer_color1) my_timer.after(2) # Watch closely and see pattern: color change, wait, dialog # Program execution was blocked and continued only after timer expired appuifw.note(u'After timer expired') # Screen goes white, because we're missing redraw callback # Dialog removal requests screen update --> blank by default # Not a defect as itself, redraw is missing on purpose def timer_crash5(): ''' Sample how to crash without timer.cancel ''' canvas.clear(get_color()) my_timer.cancel() # Error: # Application closed: # Python # E32USER-CBase 91 # Reason: # Timer is active and blocking function execution # User started same function and tried to cancel active timer # In this case function was started via keyboard event # SDK docs say: # "This panic is raised by CActiveSchedulerWait::Start() when # the CActiveSchedulerWait object has already been started." # Solution: # Avoid this situation # Note: # Everything is ok, IF you call this AFTER timer has expired my_timer.after(2) def cb_quit(): # There is possible crash if exit while timer is active # Cancel it always before exit, just in case my_timer.cancel() app_lock.signal() appuifw.app.orientation = 'portrait' appuifw.app.screen = 'full' appuifw.app.exit_key_handler = cb_quit appuifw.app.menu = [(u"Exit", cb_quit)] appuifw.app.body = canvas = appuifw.Canvas() canvas.bind(key_codes.EKey1, timer_color1) canvas.bind(key_codes.EKey2, lambda:timer_color2()) # Error: # Application closed: # Python # KERN-EXEC 3 # Reason: # Missing lambda on callback with parenthesis # Solution: # add lambda # This is invalid sample code, do not use: # canvas.bind(key_codes.EKey2, timer_color2()) # Error: # Nothing happens # Reason: # Missing parenthesis in callback with lambda # Solution: # add parenthesis # This is invalid sample code, do not use: # canvas.bind(key_codes.EKey2, lambda:timer_color2) canvas.bind(key_codes.EKey3, timer_crash3) canvas.bind(key_codes.EKey4, timer_color4) canvas.bind(key_codes.EKey5, timer_crash5) app_lock.wait()
Here are some screenshots
| Related Discussions | ||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Strange problem regarding receiving SMS | oastolen | Multimodecards | 2 | 2003-06-10 11:24 |
| How make loop with timer? | EtsiEtsi | General Symbian C++ | 2 | 2005-10-24 13:18 |
| 有关于CTimer 和 RTimer 使用的例子吗?谢谢谢谢!!!! | shuiguo009 | Symbian | 1 | 2003-09-11 01:44 |
| limited wait for server reply | noussaENSI | Symbian Networking & Messaging | 2 | 2007-04-10 13:42 |
| Phone Connectivity Issues - | robertclark | General Messaging | 1 | 2007-07-23 11:02 |

