5

我想从我的 JavaFX 应用程序中定期执行一项任务。该任务从远程流中提取数据。

虽然我知道我可以使用如下建议的计时器:

JavaFX 周期性后台任务

我相信这应该可以使用 JavaFX Service对象来完成。Javadoc 中提到了指定自定义执行器(这里想到了ScheduledThreadPoolExecutor ),但是如何指定周期和延迟?理想情况下,这将使用服务通常的启动、重置、重启和状态绑定......

public class MyFirstLineService extends Service<String> {
     private StringProperty url = new SimpleStringProperty(this, "url");
     public final void setUrl(String value) { url.set(value); }
     public final String getUrl() { return url.get(); }
     public final StringProperty urlProperty() { return url; }

     public MyFirstLineService() {
         setExecutor(new ScheduledThreadPoolExecutor());
     }

     protected Task createTask() {
         final String _url = getUrl();
         return new Task<String>() {
             protected String call() throws Exception {
                 URL u = new URL(_url);
                 BufferedReader in = new BufferedReader(
                         new InputStreamReader(u.openStream()));
                 String result = in.readLine();
                 in.close();
                 return result;
             }
         };
     }
 }
4

3 回答 3

3

JavaFX 问题跟踪器 - RT18702中请求了 ScheduledService 。

跟踪器包括尚未包含在 2.2 分支中的初步实现的源代码。如果需要,您可以查看该来源,看看它是否有助于改进您的解决方案。

于 2012-12-27T19:07:43.803 回答
2

我已经找到了一种方法来做到这一点,建立在上面 sarcan 的评论之上......

可以创建一个 Timeline 对象,通常用于为 UI 元素设置动画,作为在 FX 应用程序线程上运行的计时器。使用它可以重新启动服务对象,然后在后台线程上执行长时间运行的操作,同时通过 FX 应用程序线程绑定保留属性访问和更新。

前任:

    final MyFirstLineService svc = new MyFirstLineService();
    final Duration oneFrameAmt = Duration.seconds(5);
    final KeyFrame oneFrame = new KeyFrame(oneFrameAmt,
            new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent evt) {
                    svc.restart();
                }
            });
    Timeline timer = TimelineBuilder.create()
                            .cycleCount(Animation.INDEFINITE)
                            .keyFrames(oneFrame)
                            .build();
    timer.playFromStart();
于 2012-12-26T16:06:18.910 回答
1

遇到同样的问题。一个例子ScheduledThreadPoolExecutor可能是:

ScheduledExecutorService executor = Executors.newScheduledThreadPool(5);

Service s = new Service(){
    @Override
    protected Task<String> createTask() {
        return new Task<String>() {
            @Override
            protected String call() throws Exception {
                // code...  
            }
        };
    }
}

// created tasks shall be run in thread pool
s.setExecutor(executor);

// start the service the first time
s.start();

// restart the service every 5 seconds
s.scheduleWithFixedDelay(new Runnable() {
        @Override
        public void run() {
            // need runLater here since trigger needs to be in the javaFX thread
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    checker.restart();
                }
            });
        }
    }, 0, 5, TimeUnit.SECONDS);
}

可以用 a 来解决,Timer但是你失去了 JavaFX 数据绑定能力(正如你已经提到的)。期待Java8!

于 2013-12-11T08:29:59.843 回答