Close window in different thread

Hello,

I’m using vaadin 7.0.5 and I’m having trouble in closing a window from a different thread.
The window simply doesn’t get closed. Never. It remains in the screen even if window.close() is called.

Basically, the window shows a ProgressIndicator and it is started when a long running task is required.
The close method is called but the dialog doesn’t get closed.


        final ProgressIndicator pi = new ProgressIndicator();
        pi.setIndeterminate(false);
        pi.setEnabled(true);
        pi.setValue(0f);
        
        progressReport = new StuffProgressReport(pi);
        wdw = new ProgressWindow("Waiting", pi);
        
        wdw.show();
        String[] calculations = getData();
        Thread t = new Thread(new LongRunningTask(calculations));
        
        t.start();

In the run method of LongRunningTask there is a simple finally statements that simply calls :


        wdw.close();

ProgressWindow is defined as following:


public class ProgressWindow extends Window{
    
    private static final long serialVersionUID = 161901606322111895L;
    
    public ProgressWindow(String title, ProgressIndicator pi){
        
        VerticalLayout root = new VerticalLayout();
        root.setSizeFull();
        root.addComponent(pi);
        
        setContent(root);
        
        setWidth(300, Unit.PIXELS);
        setHeight(100, Unit.PIXELS);
    }

    public void show() {
        Console.getCurrent().addWindow(this);
    }
}

StuffProgressReport does the following. It simply refresh the ProgressIndicator about the job that is currently done.


class StuffProgressReport implements IProgressReport {
        private ProgressIndicator pi;
        private int maxStep = -1;
        private int currentStep = 0;
        private boolean isDone = false;
        private boolean isAborted = false;
        
        public StuffProgressReport(ProgressIndicator pi){
            this.pi = pi;
        }
        
        @Override
        public void begin(int totalWork) {
            this.maxStep = totalWork;
            this.currentStep = 0;
        }

        @Override
        public void setTaskName(@NonNull String taskName) {
            this.pi.setCaption(taskName);
        }

        @Override
        public void worked(int installment) {
            this.currentStep += installment;
            // progress
            if (currentStep == maxStep) {
                pi.setEnabled(false);
                pi.setValue(1f);
            } else {
                pi.setValue((float) currentStep / maxStep);
            }
        }

        @Override
        public void done() {
            this.isDone = true;
            pi.setValue(1f);
        }

        @Override
        public boolean isAborted() {
            return this.isAborted;
        }
        
        public boolean isDone() {
            return isDone;
        }
        
    }

Thanks for any help

Does it disappear if you do something else in the application, like press a button or something? I don’t see any push or poll logic in there. A roundtrip between the server and browser goes always in the this direction: Browser → Server → Browser. If you do a change in another thread than the main one, vaadin won’t send the changes automatically in the sense of Server->Browser - client has to trigger it. If you do anything in the browser that causes a roundtrip to the server, then your other thread changes will also piggyback in that roundtrip. That’s why pressing a button or changing a value might “trigger” the close even if they have nothing to do with the thread.

There the options are to do poll or push. Poll says to the browser that it should do an empty roundtrip to the server every x milliseconds, to see if there is anything have been updated. Push tells the browser to open another channel between browser and server, which the server doesn’t respond to until there is something new on the server to push trough that channel.

Yes, if I click a button the dialog disappear.

I would like to have the dialog disappear automatically … what do you suggest ? As far as I know push is supported only on vaadin 7.1.x. Isn’t it ?

Thanks

Push without the use of add-ons is only supported in Vaadin 7.1.0.beta1 + but you could use the standard
ProgressIndicator
Component which supports polling. Until you change to the newest version or start using one of the addons this would be the best (and only) option.

Thanks Marius for your answer but I’m already using ProgressIndicator (it’s show in the source code).

So, probably I’m not using it right. Could you give me an example ?

Looking at your code it looks like you call pi.setEnabled(false) in the worked method. Is it possible that you’re disabling the progress indicator, which is getting picked up in the next client poll, then later closing the window? Once the progress indicator has been disabled it will no longer poll for changes so the client will never pick up the window close state change (without using push).

You might want to leave the pi enabled but set indeterminate false and a value of 1 (or is it 100?). The pi will then continue to poll and pickup the window close state change. You could also look at using the Refresher plugin which is an invisible polling component/extension that you can leave enabled even if you disable the progress indicator.

-mike

I had a look through your code and i’m not quite sure if i understood the part with the StuffProgressReport class.

Basically you should hava a Worker thread which in the end does the changes to the UI (in your case closes the window) and then sets the value of the Progressindicator and disables the PI (like you do it in the voids worked and done). So you should make sure that this get done after the window.close method is called and not before it.

An example is in the Vaadin sampler i linked to. Also here:
demo.vaadin.com/sampler/#ui/interaction/progress-indicator

If it’s not working could you post the code in your worker?

Thanks Mike. It seems to work.

But from time to time I got the error
“A connector should not be marked as dirty while a response is being written.”

for the connector related to ProgressIndicator.

It doesn’t happen always, only sometimes.

I know I can lock the UI but if I lock the UI the ProgressIndicator doesn’t get updated.

Any hint ? Thanks,

Emanuele

Hello,

Please show the code for LongRunningTask. You
must
properly lock the session when accessing the UI from a background thread, otherwise you do get race conditions and anything can happen. This is not optional. You must hold the lock only when actually doing something with the UI and release it as soon as possible, otherwise, as you say, request threads get starved waiting for the lock.

Thanks, locking the UI works nicely.

In the past I tried to lock the UI but I think I was locking too much :slight_smile: Now I release it as soon as possible.