Async in JavaFX 1.2 Part 4

前回に引き続きまたまた懲りずに非同期処理のお話です。
もういい加減 タイトルも変更した方が良いかな...

非同期処理でやりたいこととして...

  1. ファイル入出力やDBの検索、操作やHTTPアクセス等の重い処理
  2. バックグラウンドで定期的に実行される処理
  3. 複数のタスクをシーケンシャルに実行する処理
等があります。前回までは 1. についてのお話でしたが、今回は 2. についてです。


例えば...

  • 5分に1回 Web にアクセスして表示を更新する。(FeedTask にはこの機能があるのに HttpRequest にはない...)
  • 入力内容を定期的にファイルに保存する。

等が考えられます。

以下の PeriodicalActionTask は指定した action をinterval の間隔で繰り返し実行するだけの簡単なタスクです。

実は 当初想定したものと最終的には違うものになってしまいました。
本当は前回紹介した ProgressTask のように task 属性に Task を渡し、その Task を繰り返し実行したかったのですが...
API リファレンスにも書いてありましたが、Task は 一度しか start() できなかったのです。
で 仕方なく ActionTask と同様に action 属性に function() を渡すようにしました。

PeriodicalActionTask.fx

import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.async.Task;

public class PeriodicalActionTask extends Task {

    public-init var action: function():Void;
    public-init var interval: Duration;
    public      var repeatCount = Timeline.INDEFINITE;

    var timeline: Timeline;

    override function start(): Void {
        timeline = Timeline {
            repeatCount: bind repeatCount
            autoReverse: false
            keyFrames: [
                KeyFrame { time: 0s action: action },
                KeyFrame { time: interval }
            ]
        }
        timeline.play();
    }

    override function stop(): Void {
        if (timeline != null) timeline.stop();
    }
}

※ hide1080 さんのコメントを参考に repeatCount 属性を追加してみました。

この PeriodicalActionTask を使うと、 『Async in JavaFX 1.2 Part 2』 で紹介した 「Main.fx の一部 変更した箇所」 のコードは以下のように少しだけ簡単になります。
ActionTask をそのまま渡せると更に簡単になるんだけどな...

Main.fx の一部 変更した箇所

PeriodicalActionTask {
    interval: 10s
    action: function() {
        ActionTask {
            var _result: java.util.Date;
            action: function() {
                try {
                    java.lang.Thread.sleep(10000);
                } catch (ex: java.lang.InterruptedException) {}
                _result = new java.util.Date();
            }
            onDone: function() : Void {
                result = _result;
            }
        }.start();
    }
}.start();

ということで...
今回はここまで...
次回、 『 複数のタスクをシーケンシャルに実行する 』 へ続く...