Callbacks and threads

Olivier Andrieu oandrieu at nerim.net
Mon Oct 30 20:24:06 CET 2006


 Matthieu Dubuget [Monday 30 October 2006] :
 >
 > Hello.
 > 
 > I have a button b in a little application, which I want to trig function
 > f (val f: unit -> unit) when clicked.
 > f reads some value from hardware: it lasts 2~3 s.
 > 
 > As a first try, I just did
 >  b#connect#clicked ~callback:f
 > 
 > It works as expected.
 > 
 > I know would like to:
 > - modify IHM (change cursor, disable buttons...) with : val active :
 > bool -> unit
 > - call f
 > - revert IHM modifications
 > 
 > I tried:
 > b#connect#clicked ~callback:(
 >   fun () ->
 >     active false;
 >     f ();
 >     active true;
 > )
 > 
 > f is called ok, except that:
 > - cursor change is not displayed during computation (seems like I have
 > to give control back to the main loop for this to happen?)

yes.

 > - if another button is clicked during the computation, the corresponding
 > callback is called after f has returned.
 > 
 > I then tried:
 > b#connect#clicked ~callback:(
 > (fun () ->
 >   active false ;
 >   ignore (Thread.create (fun () ->
 >     f ();
 >     active true) ())
 > )
 > 
 > Unfortunately, this way, f is nether executed?

(I don't know, I never use threads)

 > 
 > Obviously,
 > ~callback: (fun ()-> ignore (Thread.create (fun () ->
 >                                    lire_eeprom ();
 >                                   active true) ()))
 > Does not work...
 > 
 > What is the right thing to do (I mean except from stopping programming
 > and drinking a good fresh beer)?

Instead of using threads, you could execute f with an idle GTK source :
,----
| b#connect#clicked ~callback:(fun () ->
|   active false ;
|   ignore (Glib.Idle.add (fun () ->
|     f () ; 
|     active true ;
|     false)))
`----
that way the clicked handler does not execute f, it schedules it for
execution when the GTK+ mainloop is idle. When the callback returns,
GTK+ processes the UI stuff triggered by the call to `active false'
(eg changing cursors) and _then_ it will call the idle callback.

N.B.: To be really clean, the idle callback should trap exceptions:
,----
| begin
|   try f() ; active true 
|   with _ ->
|     Glib.Message.log `WARNING "complain about uncaught exception" 
| end ;
| false
`----

-- 
   Olivier




More information about the Lablgtk-list mailing list