Re: Updating GUI during long operation



Le 26/04/2013 03:59, Kip Warner a écrit :
On Sat, 2013-04-20 at 18:54 +0200, Colomban Wendling wrote:
Just never do something time consuming in the main loop thread.  If you
don't there should not be any lag.  

Hey Colomban. The time consuming task is in its own separate thread, but
it's making a GIF animation lag and user interface responsiveness as
well.

That's weird.  However, although I don't know much about Python
threading (and another guy in this thread suggests it's not really
good), I'm wondering whether your thread couldn't be simply locking
stuff used by both GUI and worker thread, effectively blocking the GUI one.

For example, your idle callback _updateGUI() uses the thread's self, so
I guess Python would lock it.  And this would mean that the callback and
the thread functions could not run concurrently.  And even worse, if the
Python thread model is based on simple functions locks (e.g. the lock is
held at the function entrance, and only released on function leaving),
this would mean the callback could never run before the thread as
finished.  I don't know, but this is an idea from where the issue might
come from.

BTW, in VerificationThread.run, which I believe is run in the thread,
right?, there are access to GTK widgets (self._assistant).  This either
requires a lock (which may be the reason why your thread would block the
main one), or it may crash (since GTK is NOT thread safe).  Anyway, I
think this should rather be done in the idle callback.  BTW, you
actually mark the page as complete in both run() and _setQuitOk() which
is called by run().

[...]

I could have tried this aforementioned event pump from outside the
updateGUI callback and done it from within the worker thread, but I
didn't know if that was thread safe to do.

I think the main loop is completely thread safe, event with this, but
again *do not do this*.  If the even loop freezes, it's that you do too
much work in it's thread, nothing else.  Check what you do in the main
thread and that takes time, and try either optimizing it or movie it to
another thread.

I think what I'll have to do is try optimizing the thread to give the
event pipeline a chance to "breath", but then that still begs the
question of the best way to do that. I thought of manually flushing the
event queue, but I don't think you can do that from the worker thread
and you mentioned it is not a good idea to do even if you could.

I don't think optimizing the worker thread is the solution for the GUI
issue.  If everything worked as it should, the worker thread could take
as much time as it wanted, and it still wouldn't block the main thread.
 That's the point of threads: doing tasks in parallel.  Of course
reducing the time the worker thread takes would reduce the UI freeze
duration, but it wouldn't solve it.

However, if most of your thread's time is lost in IO rather than
computation time (e.g. if the MD5 runs faster than the IO), you could
perhaps avoid a thread using asynchronous IO calls and computing the sum
by packets.  Something like this (in Vala pseudo-code):

        async string sum(File file) {
                var sum = new MD5();
                while (true) {
                        /* read by blocks of 2048 bytes (or whatever) */
                        var data = yield file.read_async(2048);
                        if (data) {
                                sum.push(data);
                        } else {
                                break;
                        }
                }
                return sum.hash();
        }

Here yield would work like in Vala, which basically means calling a
implicit callback which will perform the following instructions when the
asynchronous work is done.

But this doesn't explain why your program blocks the main thread, and
may very well not be practical in your case (or even, on Python, I don't
know).


Hope this could help in some way.  Regards,
Colomban



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