Pregunta

En mi aplicación SWT Java, a menudo quiero devolver información desde una llamada Display.syncExec().La mejor manera que he encontrado hasta ahora para hacer esto es:

final ArrayList<Integer> result = new ArrayList<Integer>();
GUI.display().syncExec(new Runnable(){ public void run() {
   MessageBox mb = /* ... */;
    /* set up messagebox */
   result.add(mb.open());
}});
if (SWT.OK == result.get(0)) { /* ... */ }

Creo que esto está permitido porque ArrayList es seguro para subprocesos, pero ¿hay algún contenedor mejor que debería usar o una forma completamente más sencilla?

¿Fue útil?

Solución

ArrayList no es seguro para subprocesos.Puede obtener un hilo seguro List con Collections.synchronizedList.Sin embargo, es mucho más sencillo utilizar un AtomicInteger en tu caso o AtomicReference en un caso más general.

final AtomicInteger resultAtomicInteger = new AtomicInteger();
Display.getCurrent().syncExec(new Runnable() { 
    public void run() {
        MessageBox mb = /* ... */;
            /* set up messagebox */
        resultAtomicInteger.set(mb.open());
}});
if (SWT.OK == resultAtomicInteger.get()) { /* ... */ }

Otros consejos

Acabo de abordar este problema y mi primer intento fue similar: matriz o lista de elementos del tipo deseado.Pero después de un tiempo inventé algo como esto:

abstract class MyRunnable<T> implements Runnable{
    T result;
}
MyRunnable<Integer> runBlock = new MyRunnable<Integer>(){
   MessageBox mb = /* ... */;
    /* set up messagebox */
   result = mb.open();
}
GUI.display().syncExec(runBlock);
runBlock.result; //holds a result Integer

Es mucho más ordenado y elimina variables redundantes.

POR CIERTO.Mi primer intento fue usar UIThreadRunnable, pero no quería depender de SWTBot, así que descarté esta solución.Después de crear mi propia solución, descubrí que utilizan una solución similar allí.

ArrayList es no a salvo de amenazas.De lo relevante javadoc:

Tenga en cuenta que esta implementación no está sincronizada.Si múltiples hilos acceden a una instancia de ArrayList simultáneamente, y al menos uno de los subprocesos modifica la lista estructuralmente, debe sincronizarse externamente.

Si necesita una implementación de List segura para subprocesos, se proporcionan (al menos) dos en el JDK:CopyOnWriteArrayList y Vector.

Podrías usar una matriz Integer[1] para hacerlo más conciso, pero no creo que pueda actualizar directamente una variable no final desde dentro de una clase interna anónima.

final Integer[] result = new Integer[1];

Pensé que tenías que declarar los resultados como definitivos (pero ese cambio no afectaría tu código).Dado que el subproceso actual se bloquea hasta que finaliza el subproceso interno, no creo que deba preocuparse por la sincronización (pero es posible que deba hacer que la variable viole para que pueda ver el resultado).

Si esto sucede con frecuencia, será mejor que utilice el modelo de suscripción/notificación entre su proceso y su vista.Su vista se suscribe al evento que debería activar ese cuadro de mensaje y recibe una notificación cuando se cumplen las condiciones.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top