Re: timeout



Thomas Koninckx <tkoninck esat kuleuven ac be> writes:

> I'm quite new to gtk, so please  don't shoot if the question is trivial.
> I encountered following problem:
> I would like to load and display all images contained in a
> folder. I've written some code to do this. The user start this process
> by clicking a button, which adds a  gtk_timeout. So far everything is
> fine.

What exactly does your timeout do? I am not sure I understand
completely what you are trying to do. 

> The problem is that when the timer is set rather short, and images are
> loaded as fast as the machine can handle, reaction to any button-click
> is very slow, or even nonexistent! So, when I try to pause or stop
> this process, there is no reaction. Even not when I try to close the
> window.

To make your application responsive, you should make sure GUI events
are handled within at most 50 ms and preferably faster than that. This
means there must never be 50 consecutive milliseconds where the main
loop is not running.

This is how I understand what you are trying to do:

        You have two buttons, a start- and a stop-button. When the
        start button is clicked, a process that will load all images
        from a folder is started. You would like the stop button to
        stop this process as quickly as possible.

The way I would do this is to have the start button callback install
an idle handler to do the work in small pieces. Here is a sketch:

        typedef struct ImageLoaderInfo {
                char *folder;
                GTimer *elapsed_time;
                ...;
                /* plus information needed to keep track
                 * of the state of the image loading process
                 */
        } ImageLoaderInfo;

        static guint image_loading_process = 0;
        static ImageLoaderInfo *current_loader = NULL;

        gboolean
        image_loader_idle (gpointer data)
        {
                g_timer_start (info->elapsed_time);

                while (there_is_more_work_to_do (current_loader) &&
                       g_timer_elapsed (
                               info->elapsed_time, NULL) < 0.020);
                {
                        /* do a small amount of work and
                         * update info->state
                         */

                }

                if (there_is_more_work_to_do (current_loader))
                        return TRUE; /* call me again */
                else
                {
                        /* free current_loader */
                        current_loader = NULL;
                        return FALSE; /* don't call me agagin */
                }
        }

        void
        on_start_click (GtkButton *start_button, gpointer data)
        {
                ImageLoaderInfo *info = g_new (ImageLoaderInfo, 1);

                /* fill out the info struct */

                image_loading_process = 
                        g_idle_add (image_loader_idle, info);
        }

        void
        on_stop_click (GtkButton *stop_button, gpointer data)
        {
                /* do whatever has to be done to stop the
                 * image loading
                 */

                /* stop calling image_load_idle() */
                g_source_remove (image_loading_process); 
                image_loading_process = 0;
                
                /* free current_loader */
                current_loader = NULL;
         }

Ie, install an idle handler that does the work in small pieces and
never runs for more than 20 ms at a time.

> I've played around with threads, but with little succes. 

Threads may sound like a good solution to this kind of problem, but in
reality it can get complicated, especially if you want to be able to
cancel the process, and even if you do get it right, your
application's responsiveness may still be disappointing since threads,
at least on Linux, are not fairly scheduled. This means that the
thread that runs the main loop can be starved by a worker thread, in
this case an image loader thread, leading to long delays between eg. a
mouse click and the corresponding animation on the screen.



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