maemo, project, SoftwareEngineering

Using threads to do background work for maemo python app.

One of the most common requests for Witter has been to do auto-refresh on feeds. The challenge of doing this is having to switch from a single threaded user driven app, to a multi threaded app. This brings a bunch of challenges. For me the first was wanting to separate my code into separate python files for the first time.

It took me a while to find what I needed to know, but it's not all that hard. Just not all that obvious either...

Basically you want a structure that looks like this

app-folder - application.py

app-folder - applibsfolder - __init__.py

app-folder - applibsfolder - whatever.py

where applibs folder is what ever you want to call your collection of supporting files.

The 'special' __init__.py file contains a list of imports. So for example



from whatever import *

That's important since this is how things in those supporting files are made availiable to you main code.

It can then have an import of:


Import applibsfolder

so if your whatever.py has whateverClass in it, you can now refer to it as:


Applibsfolder.whateverClass()

Once I'd figured that out, I could write a class which handled threads, which could call back into my main logic.

Basically the heart of that class is a start method that uses


threading.Thread(target=self.refreshLoop, args=args, moreargs=moreargs).start()

The refreshLoop method can then be used to drive whatever. In witter I create one thread for each of the views that needs refreshing. I pass in a refresh interval, which is used to drive a time.sleep to stop the thread doing anything between refreshes.

The other important thing I discovered is that the thread must not do anything directly with the UI. Doing so caused nasty errors which killed the app. originally my feed refresh routines used the following to raise notifications:

hildon.hildon_banner_show_information(self.window,"","Tweets Received")

This references 'self.window' and I believe this is what caused my trouble. This morning I found the following alternative:



 note = osso.SystemNote(self.osso_c)

 result = note.system_note_infoprint("Tweets Received")

This hooks from the osso context created at the start of the application. Since it is not part of your apps UI it seems to allow threads to use it without causing nasty errors.

The update methods do load data into some liststores. Which are backing the treeviews in the UI, so those can be updated, and the UI will reflect those changes.

There are of course many complications to threads that need to be controlled. Suddenly you find that resources might get updated by two things at once. One way to control this is to use some primitive locking. By setting a flag when you enter a method, and unsetting it at the end. You can attempt to provide a structure of checking whether another thread is already updating the same resources.

You can take a look at witter's source code here