2008-11-11 12 views
6

Por lo que puedo leer, se utiliza para enviar un nuevo hilo en una aplicación swing para realizar algunos trabajos de "fondo", pero ¿cuál es el beneficio de usar este hilo en lugar de uno "normal"?¿Cuál es la razón de ser de SwingWorker?

no es lo mismo usando un nuevo hilo y cuando terminar recurrir a algún método de interfaz gráfica de usuario utilizando SwingUtilities.invokeLater? ...

Qué me estoy perdiendo aquí?

http://en.wikipedia.org/wiki/SwingWorker

http://java.sun.com/products/jfc/tsc/articles/threads/threads2.html

Respuesta

10

Sí, puede lograr lo que hace un SwingWorker con vanilla threads + invokeLater. SwingWorker proporciona una forma predecible e integrada para realizar tareas en un hilo de fondo e informar resultados en el EDT. SwingWorker también agrega soporte para resultados intermedios. De nuevo, puede hacer todo esto usted mismo, pero a veces es fácil usar la solución integrada y predecible, especialmente cuando se trata de simultaneidad.

+0

* tos * forma "integrada" * tos * – Rob

+2

@Rob finalmente corrigió el error tipográfico. Solo 3 años – basszero

2

SwingWorker es una implementación de un patrón común (en .Net leí existe GuiWorker BackgroundWorker para esto), donde se tiene que hacer un trabajo en un programa de interfaz gráfica de usuario, pero mantenga la GUI receptiva. El problema es que a menudo las bibliotecas de GUI no son seguras para múltiples hilos, por lo que la forma más común de implementar dichos trabajadores es usar el bucle de mensajes de la biblioteca para transferir mensajes al bucle de eventos de la aplicación.

Estas clases le permiten actualizar fácilmente su GUI. Por lo general, tienen un método update(int status) llamado por el hilo, enviado por la clase y manejado por la GUI, mientras el hilo continúa su trabajo.

Usando hilos normales, necesitaría codificar sus propios eventos o algún otro mecanismo de mensajería para esta tarea, lo que puede ser complicado si necesita esta funcionalidad a menudo. Usando invokeLater en Java, por ejemplo, mezcle el código para actualizar la GUI en el código para hacer el trabajo. SwingWorker te permite mantener las cosas separadas.

+0

También necesita oyente con SwingWorker. ¿Asi que? – OscarRyz

+0

Lo que quise decir es que necesitaría oyentes propios (no interfaces de escucha ya creadas) para su propia gestión de eventos. SwingWorker maneja todo esto por ti. por ejemplo, puede sobrescribir el método "hecho", que se invoca cuando el trabajador finaliza. –

+0

O simplemente puede agregar un detector de cambios de propiedad en el camino –

1

para responder a su pregunta, no te faltará nada. esta clase es solo una utilidad conveniente para completar la funcionalidad que usted describió (inicie otra cadena para hacer el trabajo de fondo y luego invoque una acción final en la EDT con los resultados).

3

Un ejemplo de código:

import org.jdesktop.swingx.util.SwingWorker; // This one is from swingx 
              // another one is built in 
              // since JDK 1.6 AFAIK? 

public class SwingWorkerTest { 

    public static void main(String[] args) { 

    /** 
     * First method 
     */ 
    new Thread() { 

     public void run() { 

     /** Do work that would freeze GUI here */ 

     final Object result = new Object(); 
     java.awt.EventQueue.invokeLater(new Runnable() { 

      public void run() { 
      /** Update GUI here */ 
      } 
     }); 

     } 
    }.start(); 

    /** 
     * Second method 
     */ 
    new SwingWorker< Object , Object >() { 

     protected Object doInBackground() throws Exception { 
     /** Do work that would freeze GUI here */ 

     return null; 
     } 

     protected void done() { 
     try { 
      Object result = get(); 
      /** Update GUI here */ 
     } 
     catch (Exception ex) { 
      ex.printStackTrace(); 
      if (ex instanceof java.lang.InterruptedException) 
      return; 
     } 
     } 
    }.execute(); 
    } 

} 

La elección depende siempre de las preferencias personales y casos de uso.

El segundo método tiene una ventaja cuando se refactoriza. Puede convertir más fácilmente la clase anónima a una clase interna cuando el método en el que se utiliza es demasiado grande.

Mi preferencia personal va al segundo, porque hemos construido un marco donde se pueden agregar SwingWorkers y se ejecutan uno tras otro ...

0

SwingWorker hace que el código ejemplo trivial mucho más concisa. Sin embargo, crea una bola de barro. Las comunicaciones hacia y desde la GUI y la lógica ejecutada están todas unidas. Por lo tanto, no me gustaría ver que se use en el código de producción real.

0

SwingWorker es mucho más fácil que eliminar con tus propios hilos porque te da dos cosas que son dolorosas de forma manual, coordina el hilo entre la interfaz de usuario y el proceso en segundo plano y realiza bucles que funcionan y completan las actualizaciones. la interfaz de usuario de forma incremental, como procesar una gran cantidad de datos o cargar una lista grande. La desventaja (o ventaja) depende de cómo se mire, es que oculta la implementación subyacente, por lo que la versión futura puede tener un comportamiento, rendimiento, etc. diferente, lo que puede ser indeseable. Lo encontré bastante útil como pegamento entre un evento de interfaz de usuario y mi propio código de comando, SwingWorker mantiene el enlace a la interfaz de usuario y mi código almacena datos.

1

Cuando se trabaja con Swing, es importante saber que el procesamiento de oscilación principal (es decir, el renderizado) ocurre en un único hilo (que no es el hilo principal). Esto a menudo se llama el hilo de evento Swing o awt. Quienes estén familiarizados con el JDK pre 1.6 recordarán el error del "rectángulo gris" si pasaron demasiado tiempo en un despachador de eventos para un componente de columpio. Qué significa esto. En cualquier aplicación swing tendrás 2 hilos en ejecución con los que tendrás que lidiar ahora. Normalmente, si todas sus operaciones dentro de un despachador de eventos (el código que se activa dice cuando se hace clic en un botón) es corto (es decir, cambiando el estado de un botón siwng), puede ejecutar esto dentro del despachador de eventos. Si su aplicación llamará a un servicio web o a una base de datos, o si su estado de aplicación está impulsado por eventos externos (es decir, jms) o simplemente desea que su UI sea más interactiva (es decir, cree una lista de elementos y sea capaz de hacer otra cosa) deberías usar un hilo que no sea el hilo del evento awt (el swing principal). Entonces en estos casos genera un nuevo hilo y hace lo que debe hacer, y cuando los resultados finalmente vuelven, de alguna manera tiene que crear un evento que pueda ser ejecutado por awt/swing dispatcher. SwingWorker es un gran pequeño patrón de diseño que le permite hacer esto (de la otra manera es SwingUtilities). Es particularmente útil para buscar datos de fuentes externas o decir cálculos largos (representación de una escena de gráficos). Ayuda a automatizar el envío y la posterior reintegración de los resultados de un hilo externo (que no sea el hilo awt). Para eventos asíncronos (es decir, un evento de JMS necesita actualizar un resultado, use SwingUtilities).

Cuestiones relacionadas