2015-09-07 3 views
0

У меня есть внешний Processor.process(...) тяжелый метод, который может работать в течение длительного времени (десятки минут) в обычном случае.JavaFX завершение фоновой задачи

Я хочу показать экран загрузки с помощью кнопки «Отмена» и запустить этот Processor в фоновом режиме. Я хочу прекратить выполнение фоновой задачи, когда нажата кнопка «Отменить».

Проблема в том, что у меня есть один звонок до Processor.process(...). Если бы у меня была какая-то задача в цикле, я бы делал проверки вроде if(isCancelled()){ break; } или подобные на каждой итерации.

Есть ли способ до Окончить | убить что тяжелая задача фона? Давайте предположим, что Processor.process(...) очень долго «атомная» операция (я просто не хочу, чтобы изменить всю логику глубоко позади него, чтобы выполнить одну задачу)

Вот как я начала загрузки экрана и фоновое задание:

private void handleProcess(ActionEvent event) { 

    SomeService service = new SomeService(); 
    // ... configuring service 

    Stage loadingStage = new Stage(); 
    // ... configuring 'loading' stage 

    service.setOnSucceeded(new EventHandler<WorkerStateEvent>() { 

     @Override 
     public void handle(WorkerStateEvent t) { 
      @SuppressWarnings("unchecked") 
      Entity entity = (Entity) t.getSource().getValue(); 
      // ... do some stuff 
      loadingStage.close(); 
     } 
    }); 

    service.start();  // launch background process 
    loadingStage.show(); // show 'loading' screen 
} 

ОБНОВЛЕНО Вот Сервис для фоновой работы:

private static class SomeService extends Service<Entity> { 
    private Thread threadToStopOnCancel;   // added 
    // fields, getters, setters omitted 

    protected Task<Entity> createTask() { 

     // _params initialization omitted 
     return new Task<Entity>() { 
      protected Entity call() throws IOException { 
       threadToStopOnCancel = Thread.currentThread(); // added 
       return Processor.process(_params); 
      } 
     }; 
    } 

    @SuppressWarnings("deprecation") 
    @Override 
    protected void cancelled() { 
     if (threadToStopOnCancel != null) { threadToStopOnCancel.stop(); } // added 
     super.cancelled(); 
    } 

на данный момент, я называю service.cancel(); с загрузочного экрана. Но он просто устанавливает состояние service's в положение «ОТМЕНА», и задача все еще работает в фоновом режиме.

ответ

1

В вашем определении услуги вы можете переопределить метод cancelled() или передать EventHandler методу setOnCancelled().

См. here.

+0

Отлично, спасибо. Я обновил последний фрагмент кода, он работает сейчас, как ожидалось, но для меня это немного странно. Можете ли вы предложить что-нибудь лучше? –

+0

Я не понял, что метод 'cancel()' устарел. В любом случае вы все равно можете получить тот же эффект, создав новый 'EventHandler' для метода' setOnCancelled() ', как вы это делали с методом' setOnSucceeded() ' – pulse0ne

+0

' cancel() 'не устарело. Я добавил подавление для метода 'stop()' потока. –

Смежные вопросы