在调试应用程序时,我希望主线程在每个Runnable之后等待我使用
放入JavaFX事件队列Platform.runLater(new Runnable()... )
等待它被执行(即可见)。但是这里有两个曲折:
首先,它不是一个标准的,GUI驱动的JavaFX应用程序。它是一个显示和更新JavaFX阶段的脚本。所以结构看起来像这样:
public static void main(String [] args){
//do some calculations
SomeView someView = new SomeView(data); //SomeView is basically a wrapper for a stage
PlotUtils.plotView(someView) //displays SomeView (i.e. the stage)
//do some more calculations
someView.updateView(updatedData)
//do some more calculations
}
public class SomeView {
private static boolean viewUpdated = false;
private ObservableList<....> observableData;
public void updateView(Data data){
Platform.runLater(new Runnable() {
@Override
public void run() {
observableData.addAll(data);
boolean viewUpdated = true;
}
});
//If configured (e.g using boolean switch), wait here until
//the Runnable has been executed and the Stage has been updated.
//At the moment I am doing this by waiting until viewUpdated has been
//set to true ... but I am looking for a better solution!
}
}
其次,应该很容易禁用这个&#34;功能&#34;,即等待Runnable执行(使用当前的方法这是没有问题的,但也可以使用替代方法)。
最好的方法是什么?
E.g。有什么像阻塞版本在JavaFX线程上执行Runnable或有一个简单的方法来检查事件队列上的所有事件是否已执行/事件队列是否为空....?
答案 0 :(得分:2)
只要您不从JavaFX线程调用它,PlatformImpl.runAndWait()
也会使用倒计时锁定
答案 1 :(得分:1)
这是基于JavaFX2: Can I pause a background Task / Service?
的一般想法基本想法是向gotEnd
提交FutureTask<Void>
,然后在Platform.runLater()
上致电get()
。 FutureTask
将阻止任务完成:
get()
你 必须 在FX应用程序线程上执行此代码块,因为这会导致死锁。
如果您希望可以轻松配置,可以执行以下操作:
// on some background thread:
Runnable runnable = () -> { /* code to execute on FX Application Thread */};
FutureTask<Void> task = new FutureTask<>(runnable, null);
Platform.runLater(task);
task.get();
现在,您可以在应用程序中执行以下操作:
// Wraps an executor and pauses the current thread
// until the execution of the runnable provided to execute() is complete
// Caution! Calling the execute() method on this executor from the same thread
// used by the underlying executor will result in deadlock.
public class DebugExecutor implements Executor {
private final Executor exec ;
public DebugExecutor(Executor executor) {
this.exec = executor ;
}
@Override
public void execute(Runnable command) {
FutureTask<Void> task = new FutureTask<>(command, null);
exec.execute(command);
try {
task.get();
} catch (InterruptedException interrupt) {
throw new Error("Unexpected interruption");
} catch (ExecutionException exc) {
throw new RuntimeException(exc);
}
}
}
并替换所有来电
// for debug:
Executor frontExec = new DebugExecutor(Platform::runLater);
// for production:
// Executor frontExec = Platform::runLater ;
与Platform.runLater(...)
根据您想要的配置方式,您可以根据命令行参数或属性文件有条件地创建frontExec.execute(...);
(或者,如果您使用依赖注入框架,则可以注入它)。