Какой самый лучший способ, чтобы получить возвращаемое значение из-за asyncExec в Eclipse?

голоса
5

Я пишу плагинов Eclipse, и часто возникает ситуация, когда выполняемое задание нужно сделать паузу в течение короткого времени, запустить что-то асинхронно в потоке пользовательского интерфейса, и резюме.

Так что мой код обычно выглядит примерно так:

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!

Один из способов сделать это, чтобы иметь весь класс работы имеют некоторое поле. Другой способ заключается в использовании настраиваемого класса (а не анонимный для этого и использовать его результирующее поле данных и т.д. Какой самый лучший и самый элегантный подход?

Задан 10/12/2008 в 02:05
источник пользователем
На других языках...                            


3 ответов

голоса
7

Я думаю, что выше Container «правильный» выбор. Это может быть также для безопасности обобщенного типа. Быстрый выбор в такой ситуации является окончательной идиомой массива. Хитрость заключается в том, что через какие-либо локальные переменные ссылочные из Runnable должен быть окончательным, и, таким образом, не может быть изменен. Таким образом, вместо этого, вы используете один массив элементов, где массив является окончательным, но элемент массива может быть изменен:

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

Опять же, это «быстрое» решение для тех случаев, когда у вас есть анонимный класс, и вы хотите, чтобы дать ему место, чтобы придерживаться результата без определения конкретного класса Container.

UPDATE После того как я думал об этом немного, я понял , что это работает отлично для использования слушателя и посетителя типа , где обратный вызов в том же потоке. В этом случае, однако, Runnable выполняется в другом потоке , так что вы не гарантированы , чтобы действительно увидеть результат после возвращения syncExec. Правильное решение заключается в использовании 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());

Изменения в стоимости AtomicReference гарантированно будут видны всем потокам, так же , как если бы она была объявлена нестабильной. Это подробно описано здесь .

Ответил 10/12/2008 в 05:34
источник пользователем

голоса
4

Вы , вероятно , не следует при условии , что асинхронная Runnableбудет закончена к тому времени asyncExecвозврата вызова.

В этом случае, вы смотрите на толкая результат из слушателей в / обратных вызовах (возможно , команду), или если вы хотите иметь результат доступен позже в том же методе, используя нечто вроде java.util.concurrent.Future.

Ответил 10/12/2008 в 15:17
источник пользователем

голоса
0

Ну, если это синхронизация вы можете просто иметь держатель значения какого - то внешнего по отношению к run()методу.

Классика:

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

Где контейнер просто:

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

Это, конечно , веселый и хитроумный (еще более хитроумный создает новый список , а затем устанавливая и 1 - й элемент) , но syncExecметод блокирует , поэтому ничего плохого не выходит.

Кроме случаев , когда кто - то приходит позже , и делает это asyncExec()..

Ответил 10/12/2008 в 04:55
источник пользователем

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