When you create a SwingWorker, it creates a Callable, and wraps it in a Future:
Callablecallable = new Callable () { public T call() throws Exception { setState(StateValue.STARTED); return doInBackground(); } }; future = new FutureTask (callable) { @Override protected void done() { doneEDT(); setState(StateValue.DONE); } };
The Future will be executed by a ThreadPool (of maximum 10 threads). The doInBakground() is called, returning a value that will be used by the Future for its set() method. From this point onwards, calling the isDone() method will yield true. And this is even before the Future's done() method is called. So isDone() only means that doInBackground() terminated. Not what I was thinking.
OK, so why not use the getState() method. I see clearly that it is called by the Future right after the call to doneEDT(). But let's have a look at the doneEDT() method:
private void doneEDT() { Runnable doDone = new Runnable() { public void run() { done(); } }; if (SwingUtilities.isEventDispatchThread()) { doDone.run(); } else { doSubmit.add(doDone); } }
As you can see, if we are already in the EDT, we execute immediately the method. But we know that we are started from a ThreadPool, so this is not the case. The doSubmit, surprisingly, uses a Timer and schedules the task in 30ms. Not a SwingUtilities.invokeLater() as I expected, but the result is the same: the getState() will return DONE before we even start the done() method. The PropertyChange are notifying you of the state change. So basically, you are left to yourself.