Нажатие кнопки Vaadin выполняется не сразу

У меня есть страница с формой фильтра, несколькими кнопками и большой сеткой. Я могу искать данные на основе формы фильтра и отображать данные в сетке. Поиск данных обеспечивает поток, это может занять от секунд до минут. Когда я хочу нажать кнопку, чтобы остановить поиск (в основном, чтобы остановить поток), действие выполняется всегда после завершения потока. Но мне нужно выполнить событие щелчка во время работы потока. Кто-нибудь знает, как это сделать? :)

Пользовательский интерфейс имеет @Push (PushMode.MANUAL), и нажатие работает нормально

Упрощенный код:

@SpringComponent
@UIScope
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class DistraintSearchComponent extends CustomComponent {

    @Autowired
    private Service service
    private Button searchButton = new Button("Search");
    private Button stopButton = new Button("Stop");
    private Thread searchThread;

    public void init(){

        searchButton.addClickListener(new ClickListener() {

            @Override
            public void buttonClick(ClickEvent event) {
                searchThread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        List<Results> results = service.findByFilter(filter); //this can take some time
                        refreshGrid(results);
                        getUI().push();
                    }
                });
                searchThread.start();
            }
        });

        stopButton.addClickListener(new ClickListener() {

            @Override
            public void buttonClick(ClickEvent event) {
                searchThread.interrupt();
            }
        });

    }
}

Спасибо


person NoPa147    schedule 14.08.2018    source источник
comment
Вам нужно будет добавить код поиска / потока. Мы не знаем, как вы проверяете, когда следует прекратить поиск и что с этим может быть не так. Как узнать, когда поиск закончился (на клиенте)? Используете ли вы опрос / push, правильно обращаетесь к пользовательскому интерфейсу из другого потока?   -  person Piro says Reinstate Monica    schedule 14.08.2018
comment
@Piro Я добавил упрощенный код   -  person NoPa147    schedule 14.08.2018
comment
Вы проглатываете InterruptedException?   -  person Tatu Lund    schedule 14.08.2018
comment
@TatuLund У меня не исключение   -  person NoPa147    schedule 14.08.2018
comment
Это странно, в любом случае моя точка зрения заключалась в том, чтобы вы не проглатывали его, а бросали заново. В противном случае, например, если у вас есть большая транзакция в findByFilter (..), она не будет прервана.   -  person Tatu Lund    schedule 14.08.2018
comment
Я могу только догадываться, что делает ваша служба, но рекомендую проверить это: stackoverflow.com/questions/38880069/spring-cancel-async-task   -  person Tatu Lund    schedule 14.08.2018
comment
@TatuLund Я тоже не знаю, что на самом деле делает эта служба, это сторонняя служба, я прошу данные и жду, пока я их получу   -  person NoPa147    schedule 15.08.2018
comment
Понятно. Вероятно, это не известно о прерывании, см. Также ответ Пиро. Поскольку вы используете Spring, вы, возможно, должны использовать его @Async для создания потока вместо этого, дополнительная информация здесь: dzone.com/articles/spring-and-threads-async   -  person Tatu Lund    schedule 15.08.2018


Ответы (1)


searchThread.interrupt() не останавливает поток без взаимодействия с потоком. Из документации мы можем посмотрите, что он делает:

Если этот поток заблокирован при вызове методов wait (), wait (long) или wait (long, int) класса Object или join (), join (long), join (long, int) , sleep (long) или sleep (long, int) этого класса, то его статус прерывания будет очищен, и он получит InterruptedException.

Если этот поток заблокирован в операции ввода-вывода на прерываемом канале, тогда канал будет закрыт, состояние прерывания потока будет установлено, и поток получит исключение ClosedByInterruptException.

Если этот поток заблокирован в селекторе, то будет установлен статус прерывания потока, и он немедленно вернется из операции выбора, возможно, с ненулевым значением, как если бы был вызван метод пробуждения селектора.

Если ни одно из предыдущих условий не выполняется, то будет установлен статус прерывания этого потока.

Причина в том, что вы не можете остановить выполнение везде, это было бы много неопределенного поведения. Вместо этого вы должны остановить поток контролируемым образом.

Итак, в вашем потоке поиска (в вашем случае это, вероятно, будет внутри service.findByFilter(filter);) вы должны неоднократно проверять, должен ли поток завершиться:

 while (!Thread.currentThread().isInterrupted()) {
 // fetch another entry
}

В документации также говорится, что вы можете получать InterruptedException и ClosedByInterruptException, чтобы можно было остановить обработку при обработке этих исключений. ClosedByInterruptException равно IOException, поэтому оба исключения являются проверенными исключениями, которые все равно нужно обрабатывать, но, возможно, вы не вызываете ничего, что могло бы вызвать такое исключение.

try {
    Thread.currentThread().sleep(123);
} catch (InterruptedException e) {
    return; // return from service.findByFilter(filter);
}
person Piro says Reinstate Monica    schedule 15.08.2018