Qual è il modo migliore per ottenere un valore di ritorno di un asyncExec in Eclipse?

voti
5

Sto scrivendo plugin Eclipse, e hanno spesso una situazione in cui ha bisogno di un lavoro in esecuzione per mettere in pausa per un breve periodo, eseguire qualcosa in modo asincrono sul thread dell'interfaccia utente, e riprendere.

Quindi il mio codice di solito simile a:

Display display = Display.getDefault();
display.syncExec(new Runnable() {
    public void run() {
                // Do some calculation
                // How do I return a value from here?
    }
});
// I want to be able to use the calculation result here!

Un modo per farlo è quello di avere l'intera classe di lavoro hanno qualche campo. Un altro è quello di utilizzare una classe personalizzata (anziché anonimo per questo e usare il suo campo di dati risultante, ecc Qual è l'approccio migliore e più elegante?

È pubblicato 10/12/2008 alle 02:05
fonte dall'utente
In altre lingue...                            


3 risposte

voti
7

Credo che il contenitore di cui sopra è la scelta "giusta". Si potrebbe anche essere genericized per la sicurezza tipo. La scelta pratica in questo tipo di situazione è il linguaggio matrice finale. Il trucco è che a tutte le variabili locali indicati dal Runnable devono essere definitiva, e quindi non possono essere modificati. Così, invece, si utilizza un singolo array elemento, in cui la matrice è definitiva, ma l'elemento dell'array possono essere modificati:

final Object[] result = new Object[1];
Display display = Display.getDefault();
display.syncExec(new Runnable()
{
  public void run()
  {
    result[0] = "foo";
  }
}
System.out.println(result[0]);

Ancora una volta, questa è la soluzione "rapida" per quei casi in cui si ha una classe anonima e si vuole dare un posto di attaccare un risultato senza definire una classe contenitore specifico.

UPDATE Dopo che ho pensato a questo un po ', mi sono reso conto che questo funziona bene per l'utilizzo ascoltatore e visitatore tipo dove il callback è nello stesso thread. In questo caso, tuttavia, il Runnable esegue in un thread diverso in modo da non la garanzia di vedere effettivamente il risultato dopo i rendimenti syncExec. La soluzione corretta è quella di utilizzare un AtomicReference:

final AtomicReference<Object> result = new AtomicReference<Object>();
Display display = Display.getDefault();
display.syncExec(new Runnable()
{
  public void run()
  {
    result.set("foo");
  }
}
System.out.println(result.get());

Modifiche al valore del AtomicReference sono garantiti per essere visibile da tutti i thread, proprio come se si fosse dichiarato volatile. Questo è descritto in dettaglio qui .

Risposto il 10/12/2008 a 05:34
fonte dall'utente

voti
4

Probabilmente non dovrebbe essere assumendo che l'asincrona Runnableavrà finito con il tempo le asyncExecchiamate ritorni.

In questo caso, si sta guardando spingendo il risultato fuori nel ascoltatori / callback (possibilmente modello di comando), o se si vuole avere il risultato disponibili ad un più tardi lo stesso metodo, usando qualcosa come un java.util.concurrent.Future.

Risposto il 10/12/2008 a 15:17
fonte dall'utente

voti
0

Beh, se si tratta di sincronizzazione si può solo avere un valore di titolare di qualche tipo esterno al run()metodo.

Il classico è:

final Container container = new Container();
Display display = Display.getDefault();
display.syncExec(new Runnable()
{
  public void run()
  {
    container.setValue("foo");
  }
}
System.out.println(container.getValue());

Dove contenitore è semplicemente:

public class Container {
  private Object value;
  public Object getValue() {
    return value;
  }
  public void setValue(Object o) {
    value = o;
  }
}

Questo è naturalmente divertente e poco raccomandabile (ancor più dubbia è la creazione di un nuovo elenco e quindi impostare e ottenere il primo elemento), ma i syncExecblocchi metodo in modo nulla di male viene di esso.

Tranne quando qualcuno torna più tardi e lo rende asyncExec()..

Risposto il 10/12/2008 a 04:55
fonte dall'utente

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more