-
Задача описывается как наследник абстрактного класса
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()
, в котором можно отобразить ошибку.