lik*_*udo 4 service worker javafx-2
如何在JavaFX2中的服务和UI之间传递用户定义的对象和用户定义的(已检查的)异常?这些示例仅显示将String作为属性发送到服务,并将可观察字符串数组发送回UI.
似乎仅为简单类型定义属性.StringProperty,IntegerProperty,DoubleProperty等.目前我有一个用户定义的对象(不是简单的类型),我希望Task操作并使用它生成的输出数据进行更新.我通过Service的构造函数发送它,它通过Task的构造函数传递它.我想知道参数必须通过属性传递的限制.此外,如果在Task的操作期间抛出异常,它将如何从Service传递到UI?我只看到一个getException()方法,没有传统的throw/catch.
属性http://docs.oracle.com/javafx/2/binding/jfxpub-binding.htm
服务与任务http://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm
服务javadocs http://docs.oracle.com/javafx/2/api/javafx/concurrent/Service.html#getException()
"因为任务是专为使用JavaFX GUI应用程序的使用,它可以确保每次更改其公共属性,以及为国家,错误和事件处理程序的变更通知,所有发生的主要的JavaFX应用程序线程.访问这些属性从后台线程(包括call()方法)将导致引发运行时异常.
强烈建议使用任务运行的不可变状态初始化所有任务.这应该通过提供一个Task构造函数来完成,该构造函数接受执行Task所需的参数.不可变状态使得从任何线程使用变得容易和安全,并确保在存在多个线程时的正确性."
但是如果我的UI只在Task完成后触摸了对象,那么它应该没问题,对吧?
Service有一个签名Service<V>
,它<V>
是一个泛型类型参数,用于指定服务提供的任务中返回对象的类型.
假设您要定义一个返回Foo类型的用户定义对象的服务,那么您可以这样做:
class FooGenerator extends Service<Foo> {
protected Task createTask() {
return new Task<Foo>() {
protected Foo call() throws Exception {
return new Foo();
}
};
}
}
Run Code Online (Sandbox Code Playgroud)
要使用该服务:
FooGenerator fooGenerator = new FooGenerator();
fooGenerator.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
@Override public void handle(WorkerStateEvent t) {
Foo myNewFoo = fooGenerator.getValue();
System.out.println(myNewFoo);
}
});
fooGenerator.start();
Run Code Online (Sandbox Code Playgroud)
如果要在每次启动或重新启动之前将输入值传递到服务中,则必须更加小心.您可以将要输入的值作为服务上的可设置成员添加到服务中.在调用服务的start方法之前,可以从JavaFX应用程序线程调用这些setter.然后,在创建服务的任务时,将参数传递给服务的Task的构造函数.
执行此操作时,最好使所有信息在线程之间来回传递不可变.对于下面的示例,Foo对象作为输入参数传递给服务,Foo对象基于作为服务输出接收的输入.但是Foo本身的状态只是在它的构造函数中初始化--Foo的实例是不可变的,一旦创建就无法更改,并且它的所有成员变量都是最终的并且不能改变.这使得更容易推理程序,因为您永远不必担心另一个线程可能同时覆盖该状态.它似乎有点复杂,但它确实使一切都非常安全.
class FooModifier extends Service<Foo> {
private Foo foo;
void setFoo(Foo foo) { this.foo = foo; }
@Override protected Task createTask() {
return new FooModifierTask(foo);
}
private class FooModifierTask extends Task<Foo> {
final private Foo fooInput;
FooModifierTask(Foo fooInput) { this.fooInput = fooInput; }
@Override protected Foo call() throws Exception {
Thread.currentThread().sleep(1000);
return new Foo(fooInput);
}
}
}
class Foo {
private final int answer;
Foo() { answer = random.nextInt(100); }
Foo(Foo input) { answer = input.getAnswer() + 42; }
public int getAnswer() { return answer; }
}
Run Code Online (Sandbox Code Playgroud)
还有一个向Service
Service javadoc中的 a提供输入的示例.
要从服务返回自定义用户异常,只需在服务的任务调用处理程序中抛出用户异常.例如:
class BadFooGenerator extends Service<Foo> {
@Override protected Task createTask() {
return new Task<Foo>() {
@Override protected Foo call() throws Exception {
Thread.currentThread().sleep(1000);
throw new BadFooException();
}
};
}
}
Run Code Online (Sandbox Code Playgroud)
并且可以像这样检索异常:
BadFooGenerator badFooGenerator = new BadFooGenerator();
badFooGenerator.setOnFailed(new EventHandler<WorkerStateEvent>() {
@Override public void handle(WorkerStateEvent t) {
Throwable ouch = badFooGenerator.getException();
System.out.println(ouch.getClass().getName() + " -> " + ouch.getMessage());
}
});
badFooGenerator.start();
Run Code Online (Sandbox Code Playgroud)
我创建了几个可执行的示例,您可以使用它来尝试这一点.
归档时间: |
|
查看次数: |
2231 次 |
最近记录: |