从Eclipse中的asyncExec中获取返回值的最佳方法是什么?

Uri*_*Uri 6 eclipse eclipse-plugin anonymous-class

我正在编写Eclipse插件,并且经常出现这样的情况,即正在运行的Job需要暂停一段时间,在UI线程上异步运行并恢复.

所以我的代码通常看起来像:

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!
Run Code Online (Sandbox Code Playgroud)

一种方法是让整个Job类都有一些字段.另一种方法是使用自定义类(而不是匿名类,并使用其生成的数据字段等.什么是最好和最优雅的方法?

Dav*_*Ray 8

我认为上面的容器是"正确的"选择.它也可以是类型安全的通用化.在这种情况下的快速选择是最终的数组习语.诀窍是从Runnable引用的任何局部变量必须是最终的,因此不能修改.因此,您使用单个元素数组,其中数组是final,但可以修改数组的元素:

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]);
Run Code Online (Sandbox Code Playgroud)

同样,对于那些您拥有匿名类并且希望在不定义特定Container类的情况下为其提供结果的情况,这是"快速"解决方案.

更新 在我想到这一点后,我意识到这适用于回调在同一个线程中的监听器和访问者类型用法.但是,在这种情况下,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());
Run Code Online (Sandbox Code Playgroud)

所有线程都保证可以看到对AtomicReference值的更改,就像它被声明为volatile一样.这详细描述在这里.


jam*_*esh 4

您可能不应该假设异步Runnable将在调用返回时完成asyncExec

在这种情况下,您正在考虑将结果推送到侦听器/回调(可能是命令模式),或者如果您确实希望稍后在同一方法中使用结果,请使用java.util.concurrent.Future.