EDT and SwingWorker Thread - Publish and Process

288 Views Asked by At

EDT and SwingWorker concepts are kind of confusing. I have gone over the method definitions a couple of times now and wrote some sample programs as well.

Below is the current scenario I have,

1) I have starting a GUI window from the main method using the following,

public static void main(String[] args) {
    // TODO Auto-generated method stub
    SwingUtilities.invokeLater(new Runnable() {

        @Override
        public void run() {
            // TODO Auto-generated method stub
            final StartMainWindow StartMainWindow = new StartMainWindow();
            StartMainWindow.initActionsAndComponenets();
        }
    });
}

2) StartMainWindow is an SWT window and the main piece of code is a "RUN" button. On clicking the run button, a certain set of DB operations need to be performed which are placed in the doInBackground() method of the DBOperations class. This class extends SwingWorker.

DBOperations dbOperate = new DBOperations(currentFileToBeProcessed, currentFileListObject, unstreamOutputs, saveCanonicals, clientId, systemDestin, text, true);
dbOperate.execute();

3) I have removed all DBOperations code and put in some sample code so that its easier to understand. In DBOperations, below is the code,

public class DBOperations extends SwingWorker<Integer, String>{
    @Override
    protected Integer doInBackground() throws Exception {
        Thread.sleep(2000);
        publish("String");
        System.out.println("Entered");
        Thread.sleep(5000);
        publish("String");
        System.out.println("Entered..");
        Thread.sleep(2000);
        publish("String");
        System.out.println("Entered....");
        Thread.sleep(2000);
        publish("String");
        System.out.println("Entered......");
        publish("String");
        publish("String");
        publish("String");
        publish("String");
    }

    @Override
    protected void process(List<String> chunks) {
        // TODO Auto-generated method stub
        System.out.println("Entered text update....");
        for (String string : chunks) {
            System.out.println(string);
        }
    }
}

When I run my code, it starts a window and just prints "Entered".

After I close the window, it print whatever I have sent through using publish. So the actual sequence of events is below,

Entered
Entered..
Entered....
Entered......
**CLOSES WINDOW
String
String
String
String
String
String
String
String

On using publish, it should print to stdout immediately. Any explanations why is this happening and suggestions for fix?

1

There are 1 best solutions below

0
Dhiren Dash On

I solved this without using any SwingWorker concepts. As mentioned by MadProgrammer, SWT has its own thread model. What I ended up doing is the following,

1) Implement runnable interface on my DBOperations class. And then add a method called updateTextArea which does an asyncExec (method provided in SWT) to asynchronously append strings to the text area and also output to the stdout.

public class DBOperations implements Runnable{
    @Override
    public void run() {
      try {
        Thread.sleep(2000);
        updateTextArea("String");
        System.out.println("Entered");
        Thread.sleep(5000);
        updateTextArea("String");
        System.out.println("Entered..");
        Thread.sleep(2000);
        updateTextArea("String");
        System.out.println("Entered....");
        Thread.sleep(2000);
        updateTextArea("String");
        System.out.println("Entered......");
        /****DB operations performed here****/
        /****DB operations performed here****/
        /****DB operations performed here****/
        /****DB operations performed here****/
        updateTextArea("String");
        updateTextArea("String");
        updateTextArea("String");
        updateTextArea("String");
      } catch (InterruptedException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
      }
    }

    public void updateTextArea(String updateText) {
        Display.getDefault().asyncExec(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                text.append(updateText + "\n");
                System.out.println(updateText);
            }
        });
    }
}

asyncExec() makes sure that the text area and stdout are updated while the DBOperations are performed and this solves the problem.