4.5.6. Фоновые задачи
Механизм фоновых задач предназначен для асинхронного выполнения длительных операций на клиентском уровне без заморозки пользовательского интерфейса.
Использование фоновых задач:
-
Задача описывается как наследник абстрактного класса
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. -
Метод
handleTimeoutException()вызывается при истечении таймаута задачи. Если окно, в котором выполняется задача, закрывается, то задача останавливается без оповещения. -
Метод
run()задачи должен поддерживать возможность прерывания извне. Для этого в долгих процессах желательно периодически проверять флагTaskLifeCycle.isInterrupted(), и соответственно завершать выполнение. Кроме того, нельзя тихо проглатывать исключениеInterruptedException(или вообще все исключения). Вместо этого нужно либо вообще не перехватывать его, либо выполнять корректный выход из метода. -
Объекты
BackgroundTaskне имеют состояния. Если при реализации конкретного класса задачи не заводить полей для хранения промежуточных данных, то можно запускать несколько параллельно работающих процессов, используя единственный экземпляр задачи. -
Объект
BackgroundHandlerможно запускать (т.е. вызывать его методexecute()) всего один раз. Если требуется частый перезапуск задачи, то используйте классBackgroundTaskWrapper. -
Для показа пользователю модального окна с прогрессом и кнопкой Отмена используйте классы
BackgroundWorkWindowилиBackgroundWorkProgressWindowс набором статических методов.Для окна можно задать режим отображения прогресса и разрешить или запретить отмену фоновой задачи. -
Если внутри потока задачи необходимо использовать некоторые значения визуальных компонентов, то нужно реализовать их получение в методе
getParams(), который выполняется в потоке UI один раз при запуске задачи. В методе run() эти параметры будут доступны через методgetParams()объектаTaskLifeCycle. -
При возникновении исключительных ситуаций в потоке UI вызывается метод
BackgroundTask.handleException(), в котором можно отобразить ошибку. -
На выполнение фоновых задач влияют свойства приложения cuba.backgroundWorker.maxActiveTasksCount и cuba.backgroundWorker.timeoutCheckInterval.
|
Warning
|
В блоке Web Client фоновые задачи используют технологию HTTP push, предоставляемую фреймворком Vaadin. См. https://vaadin.com/wiki/-/wiki/Main/Working+around+push+issues для получения информации о настройке веб-серверов для использования данной технологии. |
|
Tip
|
Если вы не используете фоновую задачу, но хотите изменять состояние UI-компонентов из не-UI потока, воспользуйтесь методами интерфейса |