NoPa147
NoPa147

Reputation: 49

Vaadin button click doesn't perform immediately

I have page with filter form, a few buttons and big grid. I can search data, based on filter form, and show data in grid. Searching data provides thread, it may take about secs to mins. When I want to click button to stop searching (basically to stop thread), the action is performed always after the thread is done. But I need to perform click event while thread is working. Does somebody know how to do it? :)

UI has @Push(PushMode.MANUAL), and pushing is working fine

Simplified code:

@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();
            }
        });

    }
}

Thank you

Upvotes: 2

Views: 512

Answers (1)

Piro
Piro

Reputation: 1435

searchThread.interrupt() does not stop the thread without thread cooperating. From documentation we can see what it does:

If this thread is blocked in an invocation of the wait(), wait(long), or wait(long, int) methods of the Object class, or of the join(), join(long), join(long, int), sleep(long), or sleep(long, int), methods of this class, then its interrupt status will be cleared and it will receive an InterruptedException.

If this thread is blocked in an I/O operation upon an interruptible channel then the channel will be closed, the thread's interrupt status will be set, and the thread will receive a ClosedByInterruptException.

If this thread is blocked in a Selector then the thread's interrupt status will be set and it will return immediately from the selection operation, possibly with a non-zero value, just as if the selector's wakeup method were invoked.

If none of the previous conditions hold then this thread's interrupt status will be set.

Reason is you cannot stop execution everywhere, that would be a lot of undefined behavior. Instead you should stop your thread in controlled way.

So in your search thread (in your case it would be probably inside service.findByFilter(filter);) you should be repeatedly checking if thread should end:

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

Documentation also says that you can receive InterruptedException and ClosedByInterruptException so you can stop processing when handling this exceptions. ClosedByInterruptException is IOException so both exceptions are checked exceptions that have to be handled anyway, but maybe you do not invoke anything that would throw such exception.

try {
    Thread.currentThread().sleep(123);
} catch (InterruptedException e) {
    return; // return from service.findByFilter(filter);
}

Upvotes: 2

Related Questions