Was ist der beste Weg, um einen Rückgabewert aus einem asyncExec in Eclipse zu bekommen?

stimmen
5

Ich schreibe Eclipse-Plugins, und haben häufig eine Situation, wo ein laufender Job für eine kurze Weile pausieren muss, etwas asynchron auf dem UI-Thread ausgeführt werden, und wieder aufzunehmen.

Also mein Code sieht in der Regel so etwas wie:

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!

Eine Möglichkeit, es zu tun, ist die gesamte Job-Klasse hat einige Felder hat. Ein weiterer Grund ist eine individuelle Klasse zu verwenden (und nicht anonym für diesen und verwendet das daraus resultierendes Datenfeld, usw. Was ist der beste und eleganteste Ansatz?

Veröffentlicht am 10/12/2008 um 02:05
quelle vom benutzer
In anderen Sprachen...                            


3 antworten

stimmen
7

Ich denke, die Container über die „richtige“ Wahl. Es könnte auch für Typsicherheit genericized werden werden. Die schnelle Wahl in dieser Situation ist das letzte Array Idiom. Der Trick besteht darin, dass eine beliebige lokale Variablen aus der Runnable verwiesen endgültig sein muss und somit nicht verändert werden können. Anstatt also verwenden Sie ein einzelnes Element Array, wobei das Array endgültig, aber das Element des Arrays kann geändert werden:

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]);

Auch dies ist die „schnelle“ Lösung für die Fälle, in denen Sie eine anonyme Klasse haben, und Sie wollen, dass ihm einen Platz geben, um ein Ergebnis zu halten, ohne eine bestimmte Container-Klasse zu definieren.

UPDATE Nachdem ich diesen etwas dachte, erkannte ich dies für Zuhörer und Besucher Typ Nutzung funktioniert gut , wenn der Rückruf im selben Thread ist. In diesem Fall jedoch führt die Runnable in einem anderen Thread , so dass Sie nicht wirklich garantiert , um das Ergebnis nach syncExec kehrt zu sehen. Die richtige Lösung ist eine AtomicReference zu verwenden:

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());

Änderungen auf den Wert von AtomicReference sind garantiert von allen Threads sichtbar sein, als ob es flüchtig erklärt wurde. Dies wird im Detail beschrieben hier .

Beantwortet am 10/12/2008 um 05:34
quelle vom benutzer

stimmen
4

Sie sollten wahrscheinlich nicht unter der Annahme , dass die Asynchron Runnabledurch die Zeit , die beendet haben asyncExeckehrt Anruf.

In diesem Fall sind Sie auf der Suche das Ergebnis aus in Zuhörern / Rückrufe (möglicherweise Befehlsmuster) zu drücken, oder wenn Sie wollen in der gleichen Methode das Ergebnis zur Verfügung zu einem späteren haben, so etwas wie eine Verwendung java.util.concurrent.Future.

Beantwortet am 10/12/2008 um 15:17
quelle vom benutzer

stimmen
0

Nun, wenn es sync ist kann man nur einen Wert Inhaber einer Art außerhalb des run()Verfahrens.

Der Klassiker ist:

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

Wo Container ist nur:

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

Das ist natürlich komisch und vertrackt (noch vertrackt ist eine neue Liste erstellen und dann einstellen und das erste Element immer) , aber die syncExecMethode blockiert so nichts Schlechtes kommt davon.

Außer , wenn jemand kommt später wieder und macht es asyncExec()..

Beantwortet am 10/12/2008 um 04:55
quelle vom benutzer

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