2017-10-11 232 views
0

我有一个JavaFX 8应用程序。它采用一种观察者模式对事件做出反应:从线程库启动的线程更新JavaFX控件

public class EventBus { 

    public static final EventBus INSTANCE = new EventBus(); 

    private final Set<EventListener> listeners; 

    private EventBus() { 
     listeners = new HashSet<>(); 
    } 

    public void register(EventListener listener) { 
     listeners.add(listener); 
    } 

    public void fire(Event event) { 
     listeners.forEach(listener -> listener.eventFired(event)); 
    } 
} 

它工作得很好,到目前为止我所有usecases:

  • 带有按钮的互动从外部控制器,这是我与观察
  • 活动Platform.runLater()发起螺纹

现在我要开始电子商务嵌入Undertow HTTP服务器并在内部部署JAX-RS端点。每当有请求进入时,我想使用上述事件总线从该端点内发起一个事件。所以,我这是怎么开始暗流和部署我的JAX-RS应用:

UndertowJaxrsServer server = new UndertowJaxrsServer().start(); 
server.deploy(new MyEndpoint(eventBus)); 

的事情是,new UndertowJaxrsServer().start()是异步调用,并启动其自身的线程。然后,当MyEndpoint处理请求并尝试触发事件时,它会发生在由Undertow启动的该线程中。

所以在事件侦听器,如果我尝试做UI上的任何更新,我得到:

java.lang.IllegalStateException: Not on FX application thread; currentThread = XNIO-1 task-1 
    at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:236) 
    at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:423) 
    at javafx.scene.Parent$2.onProposedChange(Parent.java:367) 
    at com.sun.javafx.collections.VetoableListDecorator.clear(VetoableListDecorator.java:294) 
    at ui.DialogManager.showDialog(DialogManager.java:109) 

最后,我的问题是有没有办法明确告诉的JavaFX运行一段代码在UI线程中,即使调用堆栈来自另一个(我没有控制权并且我无法做到这一点)Platform.runLater()

谢谢!

回答

2

如果MyEndpoint是你的类,然后围绕fire(Event event)方法的调用与Platform.runLater()或更改EventBus类:

public class EventBus { 

    public static final EventBus INSTANCE = new EventBus(); 

    private final Set<EventListener> listeners; 

    private EventBus() { 
     listeners = new HashSet<>(); 
    } 

    public void register(EventListener listener) { 
     listeners.add(listener); 
    } 

    public void fire(Event event) { 
     Platform.runLater(() -> { 
      listeners.forEach(listener -> listener.eventFired(event));  
     }); 
    } 
} 
+0

作为优化你也可以运行火,[Platform.isFXApplicationThread()](HTTPS内的检查: //docs.oracle.com/javase/8/javafx/api/javafx/application/Platform.html#isFxApplicationThread--),如果没有在FX线程上运行,就运行,否则立即执行。 – jewelsea

+0

非常感谢!第一个提案(围绕“fire(Event event)”的调用)非常完美! – ivko