0

Consider Clutter and Enlightenment. They both provide idlers and adding event callbacks into the event loop. Neither one seems to advocate the use of threads but instead suggest event driven programming.

However, what if you have a data producer that chews up seconds of processing before returning?

Surely adding this sort of processing in the idlers or event loop will stop the UI being responsive?

How should you do these sort of things with UI frameworks?

FYI - We are using both these frameworks in Python.

Thanks.

user626201
  • 1,623
  • 3
  • 19
  • 36
  • If I read correctly clutter is combined with `gobject`. In this case you can start functions in a background thread with `gobject.idle_add(func)`. – schlamar Jun 05 '12 at 17:31
  • "The gobject.idle_add() function adds a function (specified by callback) to be called whenever there are no higher priority events pending to the default main loop" - hence I read this as the main loop context will be held by the callback - i.e. does not spawn a separate thread...? – user626201 Jun 06 '12 at 09:08
  • 1
    I meant you can try the default way from GTK how to interact with threads, see this [faq for details](http://faq.pygtk.org/index.py?req=show&file=faq20.001.htp) – schlamar Jun 06 '12 at 11:52
  • Thanks - yes, this looks like a potential winner. From the description in the FAQ, it would seem my suspicions are correct. – user626201 Jun 06 '12 at 14:50

2 Answers2

1

if your producer code cannot be broken off into small chunks, then you should definitely use threads. Clutter, like and even more so than GTK+ given the threading model of GL (the context for the state machine is stored in thread local storage), cannot be used by different threads except the one that called clutter_init() and clutter_main(); it is, on the other hand, perfectly acceptable to use the GMainLoop facilities to schedule the UI update from a thread into the main loop.

Clutter has an example on how to achieve this pattern in the Git repository:

http://git.gnome.org/browse/clutter/tree/examples/threads.c

in short, with the blocking operation being executed inside a thread, you should schedule the UI update by using gobject.idle_add().

ebassi
  • 8,648
  • 27
  • 29
  • Thanks - this is what I suspected. Am I right in assuming "cannot be used by different threads except the one that called clutter_init() and clutter_main()" can be any thread and does not necessarily need to be the same thread that called main()? – user626201 Jun 06 '12 at 14:48
  • 1
    no, Clutter initializes the GL context inside clutter_init(), to allow the creation of GL resources prior to the main loop start. so if you want to create a thread for handling the UI in Clutter, you need to use that thread to call clutter_init() *and* clutter_main(). – ebassi Jun 14 '12 at 19:59
1

There is actually a nicer way to achieve this without threads by using gobject.idle_add and a generator function:

def my_task(data):
    # ...some work...
    while heavy_work_needed:
        ...do heavy work here...
        progress_label.set_text(data) # here we update parts of UI
        # there's more work, return True
        yield True
    # no more work, return False
    yield False

def on_start_my_task_button_click(data):
    task = my_task(data)
    gobject.idle_add(task.next)

See this FAQ entry for details

schlamar
  • 9,238
  • 3
  • 38
  • 76