Hello I have been trying to learn on how to use SwingWorker to update the GUI of swing apps.
My question is this: if I have 2 swingworkers that can run concurrently (each one is fired from a different button) how to make sure that their done method is called in the EDT (to update the gui) in the same order they were fired?
My observations and ideas: I have tried to synchronize their doInBackground() methods to a lock to make sure that one has to wait for the other to finish doing their task before proceeding. The problem is that I have been able (just a few times) to see swingworker_1 finishing the doInBackground() (while the 2nd worker is waiting in the synchronized block), but the done method of the swingworker_2 was able to be called by the EDT before swingworker_1's done method even though swingworker_2 finished after. I thought about using publish just before the doInBackground() returns, this seems to always work, but might be a bad practice as it seems to be used for intermediate results and not the final results? Another possibility would be to use SwingUtilities.invokeLater inside the doInBackground() to update the gui before returning, again I am afraid it might be a bad practice as well. Thanks in advance.
The test I used, pressing the first button and then immediately the second one:
//Code that runs in the first button
SwingWorker<Void, Void> swingworker = new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
synchronized (lock) {
System.out.println("Thread 1");
Thread.sleep(1000);
return null;
}
}
@Override
protected void done() {
System.out.println("Done with thread 1 ");
//update GUI
}
};
swingworker.execute();
//Code that runs in the second button
SwingWorker<Void, Void> swingworker = new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
synchronized (lock) {
System.out.println("Thread 2");
return null;
}
}
@Override
protected void done() {
System.out.println("Done with thread 2 ");
//update GUI
}
};
swingworker.execute();
UPDATE: Just to clarify I am not concerned with who starts first (swingworker_1 or swingworker_2) that just depends on which button would be pressed first. What I want to guarantee is that if a worker from a button was the first to execute (and thus finish as the workers are synchronized in the doInBackground() method) then it should also be the first to enqueue to update the gui in the EDT. What I have found is that this does not necessarily happen even if the workers are synchronized sometimes the worker that starts the task later still manages to update the gui before the first one.