From: Olivier Andrieu MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Message-ID: <17734.20822.121335.959037 at karryall.dnsalias.org> Date: Mon, 30 Oct 2006 20:24:06 +0100 To: matthieu.dubuget at laposte.net Cc: lablgtk at math.nagoya-u.ac.jp Subject: Re: Callbacks and threads In-Reply-To: <4545E762.9010000 at laposte.net> References: <4545E762.9010000 at laposte.net> Content-Type: text/plain; charset=us-ascii Content-Length: 2222 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