2017-10-11 60 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