我想知道是否有人找到了在JavaFX 8(jdk 1.8.0_31)WebView
中正确处理超时的方法。问题如下:
假设您有一个
WebView
的实例,并告诉它一个特定的URL给load
。此外,您希望在加载文档后对其进行处理,因此将侦听器附加到为web视图供电的WebEngine
的LoadWorker
的stateProperty
。然而,某个网站在加载过程中超时,这导致stateProperty转换为Worker.State.RUNNING
并停留在那里。
然后web引擎完全卡住。我想实现一个检测超时并取消加载的系统。为此,我考虑在progressProperty
中添加一个监听器,并使用某种形式的Timer
。想法如下:
我们在web视图上启动加载请求。超时计时器立即开始运行。每次进度更新时,计时器都会重置。如果进度达到100%,计时器将无效并停止。但是,如果计时器结束(因为在特定时间段内没有进度更新,我们假设超时),则加载请求将被取消,并引发错误。
有人知道实现这一点的最佳方法吗?
问候
更新
我生成了一个代码片段,其中包含问题中描述的行为。唯一仍然困扰我的是,我无法取消LoadWorker
:调用LoadWorker#cancel
挂起(函数永远不会返回)。
public class TimeOutWebEngine implements Runnable{
private final WebEngine engine = new WebEngine();
private ScheduledExecutorService exec;
private ScheduledFuture<?> future;
private long timeOutPeriod;
private TimeUnit timeOutTimeUnit;
public TimeOutWebEngine() {
engine.getLoadWorker().progressProperty().addListener((ObservableValue<? extends Number> observable, Number oldValue, Number newValue) -> {
if (future != null) future.cancel(false);
if (newValue.doubleValue() < 1.0) scheduleTimer();
else cleanUp();
});
}
public void load(String s, long timeOutPeriod, TimeUnit timeOutTimeUnit){
this.timeOutPeriod = timeOutPeriod;
this.timeOutTimeUnit = timeOutTimeUnit;
exec = Executors.newSingleThreadScheduledExecutor();
engine.load(s);
}
private void scheduleTimer(){
future = exec.schedule(TimeOutWebEngine.this, timeOutPeriod, timeOutTimeUnit);
}
private void cleanUp(){
future = null;
exec.shutdownNow();
}
@Override
public void run() {
System.err.println("TIMED OUT");
// This function call stalls...
// engine.getLoadWorker().cancel();
cleanUp();
}
}
我认为您现在无法正确处理超时。查看此方法。正如您所看到的,它具有setReadTimeout
方法的硬编码值。这是否意味着SocketTimeoutException异常将在加载站点一小时后引发。只有在该事件之后,状态才会更改为FAILED。
所以,你现在只有一种方法:尝试破解这个问题,使用定时器,如上所述。
p.S。尝试在JavaFX问题跟踪器中创建问题。可能有人在5年后修复它。。。
我也有同样的问题,使用了一个简单的PauseTransition。同样的行为,没那么复杂