Jump to content

Alguien que me ayude con un método asíncrono please?


Recommended Posts

No entiendo la lógica de los métodos asíncronos, he tratado de hacer algo por mi cuenta, pero no me funciona. Estoy programando en Vala, es un método que carga thumbnails de forma asíncrona. Son los thumbnails que están en una lista de strings que contiene la dirección de la imagen. Tengo que hacerlo de forma asíncrona, porque si no lo hago así, si la lista de imágenes es muy larga, o hay imágenes muy grandes, el programa se me demora mucho en mostrar la interfaz gráfica.

 

He visto que algunos ocupan YELD, pero no entiendo su utilidad. Otros ocupan enumeradores, o que se yo, no entiendo muy bien la lógica detrás de esto. Si alguien pudiera modificar este código para hacerlo funcionar sería genial. Estoy seguro que hay que hacerle muy pocos cambios para que funcione, ya que la versión no asíncrona funcionaba perfecto.

 

Un millón de gracias!!

 

  	 public async void load_thumbs(){

  	 pane.set_visible(false);
  	 pane.newmodel = new Gtk.ListStore (2, typeof (Gdk.Pixbuf), typeof (string));
  	 pane.set_selection_mode (Gtk.SelectionMode.SINGLE);
  	 pane.set_pixbuf_column (0);
  	 pane.set_model(pane.newmodel);

  	 //Add thumbnails to the iconview
  	 string buff;
  	 for(int i=1; i<pane.image_list.size; i++){
       buff = pane.image_list.get_full_filename(i);
           var file = File.new_for_path (buff);
       Gdk.Pixbuf image = null;
       try{
           image.new_from_stream_at_scale_async (file.read(),110,80,false);
           stdout.printf("Added %s to thumbnail\n", buff);
     			  // Add the image name and thumbnail to the IconView
  				 Gtk.TreeIter root;
  				 pane.newmodel.append(out root);
  				 pane.newmodel.set(root, 0, image, -1);
  				 pane.newmodel.set(root, 1, pane.image_list.get_filename(i), -1);
	       	 // Select the thumbnail if it is the first in list
		        if (i==1) {
		       	 pane.select_path (pane.newmodel.get_path (root));
		            }    
		        pane.iters.append (root);
       }
       catch(Error e){
           warning (e.message);
       }
  	 }
  	 pane.selection_changed.connect (update_selected);
  	 pane.set_sensitive(true);
  	 this.queue_draw();

   }

Link to comment
Share on other sites

Personalmente no he trabajado con Vala, pero si he investigado sobre el tema......se me ocurre que podrias dividir la carga de imágenes por medio de hilos y asi separas tareas y ahorras tiempo, además de ser asíncrono de cierta forma; te dejo unos ejemplos que de verdad no son tan complicados y la lógica es bien fácil de comprender:

https://live.gnome.org/Vala/ThreadingSamples

 

Saludos :krider:

Link to comment
Share on other sites

Personalmente no he trabajado con Vala, pero si he investigado sobre el tema......se me ocurre que podrias dividir la carga de imágenes por medio de hilos y asi separas tareas y ahorras tiempo, además de ser asíncrono de cierta forma; te dejo unos ejemplos que de verdad no son tan complicados y la lógica es bien fácil de comprender:

https://live.gnome.o...hreadingSamples

 

Saludos :krider:

 

Lo intenté con threads, el problema es que Gtk no es un toolkit seguro de threads externos, como lo explico, gtk ejecuta un loop principal, y en ese loop no se puede meter otro thread, hay que hacer algo para que funcione cada vez que te quieras "meter" en el loop principal, y tras un intento fallido, mejor decidí hacerlo con async. Además es lo que me recomendó un programador apodado Nemequ que es bien conocido y el loco es terrible seco XD.

 

 

Y bueno, para

cañangasñangas

 

 

Básicamente es un iconview, que es un widget de gtk que te carga puros íconos chicos que se pueden seleccionar, como si fueran un botón, y que se acomodan al espacio que les des, se acomodan como una lista, o una fila, o una tabla, osea, es un widget súper potente, de lo más potente que tiene gtk. La idea es mostrar ahí varios thumbnails, previsualizaciones de imágenes. Lo que pasa es que estoy haciendo un visor de imágenes. Entonces al hacer click en estas imágenes, en teoría debería cambiarte a la imagen y así.

 

El código que hice en un comienzo funciona perfecto, filete, mira, te muestro una imagen de cómo se ve:

 

Capturadepantallade2012-05-31221910.png

 

El problema que tiene es que se demora mucho en cargar, por lo que pensé que sería mejor que fuera cargando como un método asíncrono, para no bloquear la interfaz. Es precisamente eso lo que no he logrado.

 

La página del proyecto:

 

https://launchpad.net/foto

 

Si no me equivoco, el último commit que subí, fue una versión que usaba threads, y funcionaba, pero tenía que hacerle join al thread (esperar a que terminara) o sino no me funcionaba, me mostraba tres imágenes en la lista, y después de unos segundos, desaparecían. Con gusto lo hago con threads, pero si me dicen como arreglar el problema que me daba XD

 

Si les interesa compilar, necesitan gtk 3, vala 0.18 libgranite, libgee y no me acuerdo qué más

Edited by zafrada
Link to comment
Share on other sites

Este ejemplo te puede servir:

http://blogs.gnome.o...ethods-in-vala/

 

Saludos ;)

Como si no lo hubiera visto :tonto:

 

Ese código es viejo, del 2009 cuando los métodos asíncronos se agregaron a Vala como característica experimental. Es difícil programar en Vala si no se está inmerso en el proyecto gnome, porque muchos de los ejemplos de la sintaxis misma del lenguaje son antiguas y no han sido actualizadas.

 

De todas formas por si a alguien le sirve, obtuve una respuesta en forma de código de Nemequ, acá se los dejo, y bueno, cuando lo adapte en mi programa, postearé cómo me quedó el mío. Probablemente tenga que crear otro método.

 

 

public async void load (Gtk.Image img, string filename) {
 GLib.File file = GLib.File.new_for_commandline_arg (filename);
 try {
GLib.InputStream stream = yield file.read_async ();
Gdk.Pixbuf pixbuf = yield Gdk.Pixbuf.new_from_stream_at_scale_async (stream, 320, -1, true);
img.set_from_pixbuf (pixbuf);
 } catch ( GLib.Error e ) {
GLib.error (e.message);
 }
}
private static int main (string[] args) {
 GLib.return_val_if_fail (args.length > 1, -1);
 Gtk.init (ref args);
 Gtk.Window win = new Gtk.Window ();
 win.destroy.connect (() => {
  Gtk.main_quit ();
});
 Gtk.Image image = new Gtk.Image ();
 win.add (image);
 load.begin (image, args[1], (obj, async_res) => {
  GLib.debug ("Finished loading.");
});
 win.show_all ();
 Gtk.main ();
 return 0;
}

 

 

Edit: Mi código ya funciona!!! =D

 

así me quedó:

 

 public void load_thumbs(){
 pane.set_visible(false);
 pane.newmodel = new Gtk.ListStore (2, typeof (Gdk.Pixbuf), typeof (string));
 pane.set_selection_mode (Gtk.SelectionMode.SINGLE);
 pane.set_pixbuf_column (0);
 pane.set_model(pane.newmodel);
 string icon_style = """
	  .thumbnail-view {
			    background-color: #FFFFFF;
		    }
		    .thumbnail-view:selected {
			    background-color: #9D9D9D;
			    border-color: shade (mix (rgb (34, 255, 120), #fff, 0.5), 0.9);
		    }
	    """;
 var icon_view_style = new Gtk.CssProvider ();
	    try {
		    icon_view_style.load_from_data (icon_style, -1);
	    } catch (Error e) {
		    warning (e.message);
	    }
	    pane.get_style_context ().add_class ("thumbnail-view");
 pane.get_style_context ().add_provider (icon_view_style, Gtk.STYLE_PROVIDER_PRIORITY_THEME);
 //Add thumbnails to the iconview
 string buff1, buff2;
 for(int i=1; i<pane.image_list.size; i++){
 buff1 = pane.image_list.get_full_filename(i);
 buff2 = pane.image_list.get_filename(i);
 load_image_async.begin (buff2, buff1, (obj, async_res) => {
    GLib.debug ("Finished loading.");
  });
 }
 pane.selection_changed.connect (update_selected);
 pane.set_sensitive(true);
 this.queue_draw();
   }

   private async void load_image_async (string filename, string full_filename) {
  GLib.File file = GLib.File.new_for_commandline_arg (full_filename);
  try {
 GLib.InputStream stream = yield file.read_async ();
 Gdk.Pixbuf image = yield Gdk.Pixbuf.new_from_stream_at_scale_async (stream, 110, -1, true);
    // Add the image name and thumbnail to the IconView
 Gtk.TreeIter root;
 pane.newmodel.append(out root);
 pane.newmodel.set(root, 0, image, -1);
 pane.newmodel.set(root, 1, filename, -1);
	    pane.iters.append (root);	
 stdout.printf("Added %s to thumbnailn", filename);
  } catch ( GLib.Error e ) {
 GLib.error (e.message);
  }
   }

 

Ahora subiré un commit con la lista de imágenes funcionando al 100% por si a alguien le interesa. Los siguientes pasos son dar la opción para ocultar la barra y esas cosas.

Edited by zafrada
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...