3.5.8. 后台任务
后台任务机制用于在客户端层异步执行任务,不阻塞用户界面。
要使用后台任务,请执行以下操作:
-
定义一个继承自
BackgroundTask
抽象类的任务。将界面控制器的引用传递给任务的构造器,该控制器将与任务和任务超时关联起来。关闭界面将中断与其相关的任务。此外,任务将在指定的超时后自动中断。
任务执行的实际操作在run()方法中实现。
-
通过将任务实例传递给
BackgroundWorker
bean 的handle()
方法,创建一个控制任务的BackgroundTaskHandler
类。可以通过在界面控制器中注入或通过AppBeans
类来获得对BackgroundWorker
的引用。 -
通过调用
BackgroundTaskHandler
的execute()
方法来运行任务。
UI 组件的状态和数据容器不能在 |
示例:
@Inject
protected BackgroundWorker backgroundWorker;
@Override
public void init(Map<String, Object> params) {
// Create task with 10 sec timeout and this screen as owner
BackgroundTask<Integer, Void> task = new BackgroundTask<Integer, Void>(10, this) {
@Override
public Void run(TaskLifeCycle<Integer> taskLifeCycle) throws Exception {
// Do something in background thread
for (int i = 0; i < 5; i++) {
TimeUnit.SECONDS.sleep(1); // time consuming computations
taskLifeCycle.publish(i); // publish current progress to show it in progress() method
}
return null;
}
@Override
public void canceled() {
// Do something in UI thread if the task is canceled
}
@Override
public void done(Void result) {
// Do something in UI thread when the task is done
}
@Override
public void progress(List<Integer> changes) {
// Show current progress in UI thread
}
};
// Get task handler object and run the task
BackgroundTaskHandler taskHandler = backgroundWorker.handle(task);
taskHandler.execute();
}
JavaDocs 中提供了 BackgroundTask
、TaskLifeCycle
、BackgroundTaskHandler
类的有关方法的详细信息。
请注意以下事项:
-
BackgroundTask<T, V>
是一个参数化类:-
T
− 显示任务进度的对象类型。在工作线程中调用TaskLifeCycle.publish()
期间,将此类型对象传递给任务的progress()
方法。 -
V
− 任务结果类型被传递给done()
方法。它也可以通过调用BackgroundTaskHandler.getResult()
方法获得,该方法将等待任务完成。
-
-
canceled()
方法只在受控的任务取消时被调用,即在TaskHandler
中调用cancel()
时。 -
handleTimeoutException()
方法在任务超时时被调用。如果正在运行任务的窗口关闭,则任务将在没有通知的情况下停止。
-
任务的
run()
方法应该支持外部中断。要确保这一点,建议在长时间运行的处理中定期检查TaskLifeCycle.isInterrupted()
标识,并在需要时停止执行。另外,不应该静默地忽略掉InterruptedException
(或任何其它异常) - 而应该正确退出方法或根本不处理异常(将异常暴露给调用方)。-
isCancelled()
如果通过调用cancel()
方法中断任务,则此方法返回true
。public String run(TaskLifeCycle<Integer> taskLifeCycle) { for (int i = 0; i < 9_000_000; i++) { if (taskLifeCycle.isCancelled()) { log.info(" >>> Task was cancelled"); break; } else { log.info(" >>> Task is working: iteration #" + i); } } return "Done"; }
-
-
BackgroundTask
对象是无状态的。如果在实现任务类时没有为临时数据创建字段,则可以使用单个任务实例启动多个并行进程。 -
BackgroundHandler
对象(它的execute()
方法)只能被启动一次。如果需要经常重启任务,请使用BackgroundTaskWrapper
类。 -
使用带有一组静态方法的
BackgroundWorkWindow
类或BackgroundWorkProgressWindow
类来显示带进度指示器和 Cancel 按钮的模式窗口。可以定义进度指示类型,并允许或禁止取消窗口的后台任务。 -
如果需要在任务线程中使用可视化组件的某个值,应该通过
getParams()
方法来获取,该方法在任务启动时在 UI 线程中运行一次。在 run()方法中,可以通过TaskLifeCycle
对象的getParams()
方法访问这些参数。 -
如果发生任何异常,框架将在 UI 线程中调用
BackgroundTask.handleException()
方法,该方法可用于显示错误。 -
后台任务受cuba.backgroundWorker.maxActiveTasksCount和cuba.backgroundWorker.timeoutCheckInterval应用程序属性的影响。
在 Web 客户端中,后台任务是使用 Vaadin 框架提供的 HTTP 推送实现的。有关如何为此技术设置 Web 服务器的信息,请参阅 https://vaadin.com/wiki/-/wiki/Main/Working+around+push+issues 。 |
如果不使用后台任务,但想要从非 UI 线程更新 UI 状态,请使用 |