Re: GUI freeze and long blocking operation



On Fri, 2013-06-14 at 15:08 +0900, Tristan Van Berkom wrote:
On Fri, Jun 14, 2013 at 8:28 AM, Kip Warner <kip thevertigo com> wrote:
On Thu, 2013-06-13 at 08:59 +0100, jcupitt gmail com wrote:
Hi Kip,

Hey John,

There are two easy ways to do a long operation in Python.

First, with idle_add(). Your callback should run for no more than 50ms
or so before returning. If you need to do more work than that, just
wait to be called again. Do not process events, you can leave that up
to the main loop. This style is handy for non-blocking, background
tasks that don't need interaction from the user.

Ok, fair enough. I didn't know idle callbacks were intended to be used
only for fast non-blocking tasks.

Secondly, with a regular loop that takes control for a long period.
You can keep the GUI alive by processing events, as you say above.
This style is better for modal actions that either block the GUI or
may require interaction.

So as I mentioned I tried abandoning the idle_add() approach and instead
relied on calling the worker function directly.

It sounds like you have done both at the same time, which seems
confusing to me. I'd make a pure 2) one. If the GUI doesn't refresh,
you probably have a bug in your code somewhere.

I do this by calling the long job function directly from within the
GtkAssistant's "prepare" signal callback immediately. The problem is
that the GUI doesn't refresh throughout the duration of the long job,
even though I do explicitly pump the message queue by calling
_updateGUI() method regularly:

Kip,
   Let me try to illustrate what you need to do to make this work.

What you currently have is:
~~~~~~~~~~~~~~~~~~~~~

prepare_signal_callback ()
{
    /* Update the GUI and flush the event queue, only once, at the
beginning of your operation */
    while (gtk_events_pending())
        gtk_main_iteration_do ();


    /* Process some data that takes a long time, without ever again
updating the GUI */
    while (there_is_data)
        process_data();
}

Hey Tristan. I see what you mean, but I think I should have provided
more code to show that what I was actually doing I think was what your
followup suggestion was. Namely do some short work, update the GUI, do
some more short work, repeat.

    <http://pastebin.com/DzrT7Fa7>

So line 140 is the "prepare" signal callback which calls the long job
startDiscVerification(). The latter is a long job which repeatedly calls
_calculateChecksum(). But during each call to the latter,  _updateGUI()
is called which pumps the message queue.

-- 
Kip Warner -- Software Engineer
OpenPGP encrypted/signed mail preferred
http://www.thevertigo.com


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]