Search code examples
javaperformanceswingswingworkerpropertychangelistener

SwingWorker: propertyChange called seldomly


I seem to have a problem with SwingWorker. I basically implemented the Java Example Code updating the UI from the propertyChange() method of my JFrame.

I also copied the sleep up to one second part in doInBackground. This leaves me with a good update rate of setProgress within my Worker.

However the propertyChange Event is fired only once about every 10sec. I know from the API that not every setProgress fires an event, and I'm ok with that, however it seems that this is kinda slow and too many events are lost.

When stepping through in a Debugger I get a better rate, ~once every 3 calls to setProgress

Any ideas why it is so slow?

Here are the parts of my Code:

public Void doInBackground() {
    Random random = new Random();
    setProgress(0);
    float getSize=0,gotSize=0;
    while (Sync.syncing) {
        //Sleep for up to one second.
        try {
             Thread.sleep(random.nextInt(1000));
        } catch (InterruptedException ignore) {
            ignore.printStackTrace();
        }
        try{
            getSize=Main.getSyncGet();
            gotSize=Main.getSyncGot();
            System.out.println("setProgress: "+(gotSize/getSize));
            setProgress((int)((gotSize/(getSize))*100));
        }catch(Exception e){
            Main.LOGGER.log(Level.WARNING,"Error setting progress",e);
        }
    }
    return null;
}

public void propertyChange(PropertyChangeEvent evt) {
        if ("progress" == evt.getPropertyName()) {
            jpb.setValue((Integer) evt.getNewValue());
        }
}

Kind Regards

Jens


Solution

  • Your problem is quite possibly here:

    System.out.println("setProgress: "+(gotSize/getSize));
    setProgress((int)((gotSize/(getSize))*100));
    

    Have you tested that the progress is actually being changed? A better println would be:

    int value = (int)((gotSize/(getSize))*100);
    System.out.println("setProgress: "+ value);
    setProgress(value);
    

    Now check to see if value is in fact changing.

    Ooops, this is definitely wrong:

    public void propertyChange(PropertyChangeEvent evt) {
            if ("progress" == evt.getPropertyName()) {
                jpb.setValue((Integer) evt.getNewValue());
            }
    }
    

    Don't compare Strings using ==. Use the equals(...) or the equalsIgnoreCase(...) method instead. Understand that == checks if the two objects are the same which is not what you're interested in. The methods on the other hand check if the two Strings have the same characters in the same order, and that's what matters here. So instead of

    if (fu == "bar") {
      // do something
    }
    

    do,

    if ("bar".equals(fu)) {
      // do something
    }
    

    or,

    if ("bar".equalsIgnoreCase(fu)) {
      // do something
    }