4.5.6.1. Использование фоновых задач
-
Задача описывается как наследник абстрактного класса
BackgroundTask
. В конструктор задачи необходимо передать ссылку на контроллер экрана, с которым будет связана задача, и значение таймаута ее выполнения.Если экран указан, то при его закрытии пользователем активная задача будет прервана. Кроме того, задача будет автоматически прервана по истечении указанного таймаута.
Собственно действия, выполняемые задачей, реализуются в методе
run()
. -
Создается объект управления задачей −
BackgroundTaskHandler
. Для этого экземпляр задачи необходимо передать методуhandle()
бинаBackgroundWorker
. Ссылку наBackgroundWorker
можно получить инжекцией в контроллер экрана, либо статическим методом классаAppBeans
. -
Выполняется запуск задачи.
Пример:
@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
− тип объектов, показывающих прогресс задачи. Объекты этого типа передаются в методprogress()
задачи при вызовеTaskLifeCycle.publish()
в рабочем потоке. -
V
− тип результата задачи, он передается в методdone()
. Его также можно получить вызовом методаBackgroundTaskHandler.getResult()
, что приведет к ожиданию завершения задачи.
-
-
Метод
canceled()
вызывается только в случае управляемой отмены задачи, то есть при вызовеcancel()
уTaskHandler
. -
Если у задачи истек таймаут, или было закрыто окно, в котором она исполнялась, то задача будет завершена без уведомлений. В блоке Web Client завершение по таймауту производится с задержкой, задаваемой свойством приложения
cuba.backgroundWorker.maxClientLatencySeconds
. -
Метод
run()
задачи должен поддерживать возможность прерывания извне. Для этого в долгих процессах желательно периодически проверять флагTaskLifeCycle.isInterrupted()
, и соответственно завершать выполнение. Кроме того, нельзя тихо проглатывать исключениеInterruptedException
(или вообще все исключения). Вместо этого нужно либо вообще не перехватывать его, либо выполнять корректный выход из метода. -
Объекты
BackgroundTask
не имеют состояния. Если при реализации конкретного класса задачи не заводить полей для хранения промежуточных данных, то можно запускать несколько параллельно работающих процессов, используя единственный экземпляр задачи. -
Объект
BackgroundHandler
можно запускать (т.е. вызывать его методexecute()
) всего один раз. Если требуется частый перезапуск задачи, то используйте классBackgroundTaskWrapper
. -
Для показа пользователю модального окна с прогрессом и кнопкой Отмена используйте классы
BackgroundWorkWindow
илиBackgroundWorkProgressWindow
с набором статических методов.Для окна можно задать режим отображения прогресса и разрешить или запретить отмену фоновой задачи. -
Если внутри потока задачи необходимо использовать некоторые значения визуальных компонентов, то нужно реализовать их получение в методе
getParams()
, который выполняется в потоке UI один раз при запуске задачи. В методе run() эти параметры будут доступны через методgetParams()
объектаTaskLifeCycle
. -
При возникновении исключительных ситуаций в потоке UI вызывается метод
BackgroundTask.handleException()
, в котором можно отобразить ошибку.