Re: [Vala] How to write a responsive GTK+ app that reads a file in the background?



On Thu, 2011-09-29 at 00:25 -0300, Leonardo Ferreira Fontenelle wrote:
I'm trying to port a small Python GTK+ application to Vala. Overall, I
have succeeded, with some very interesting performance gains. But in
some cases the search may take a few seconds to finish, while the
application reads data from the disk. I tried using an async method to
keep the user interface responsive, but it didn't work: until the search
is completed, the user can't even move the cursor in the text entry
widget. What am I missing?

This is the relevant code; I hope the names are sufficiently
descriptive.



public void on_search_entry_activate (Gtk.Entry entry) {
      
      this.timer.start();
      
      this.search_progressbar.show();
      this.search_treeview.set_model(null);
      this.search_results.clear(); // this is a Gtk.ListStore
      
      string entry_text = entry.get_text();
      stdout.printf("Searching for: %s\n", entry_text);
      string[] words = this.word_regex.split(entry_text);
      this.search.begin(words, (obj, res) => {
              this.search.end(res);
              this.search_treeview.set_model(this.search_results);
              this.timer.stop();
              stdout.printf("%fs elapsed\n", this.timer.elapsed());
              this.search_progressbar.hide();
              this.search_progressbar.set_fraction(0.0);
      });
}

public async void search (string[] words) {
      
      Gee.TreeSet<int32> matches = get_matches (words);
      
      string code, title, inclusion_notes, exclusion_notes;
      //user-relevant data
      Gtk.TreeIter iter;
      double fraction = 0.0;
      double increment = 1.0 / matches.size;
        int i count = 0;
      
      foreach (int32 match in matches) {
              get_node(match, out code, out title, out
              inclusion_notes, out exclusion_notes);
Probably:
                yield get_node(match, out code, out title, out
                               inclusion_notes, out exclusion_notes);
              this.search_results.append(out iter);
              this.search_results.set(iter, 0, match, 1, code, 2,
              title);
              fraction += increment;
              this.search_progressbar.set_fraction(fraction);
If get_node cannot be simply yielded:
                if ((++count % 1024) == 0) {
                        yield;
                }
      }
}



Thanks in advance, 

Leonardo Fontenelle

The problem is that by marking method async you move computation to
different part of code (in fact IIRC the returning of result in this
case) but not splitting it.

To get the speedout you should:

 - yield all I/O actions
 - split long computations by yield

Alternatively you can use threads but:

 - Threads are move heavyweight as they are system threads
 - Threads use real parallelism. It means that you can take advantage of
multi-core CPU
   - But IIRC the GDK/GTK+ is not thread-safe by default. You need to
add an additional calls to make it safe

Regards

Attachment: signature.asc
Description: This is a digitally signed message part



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