Managing Long-Running Tasks in a Swing App
If you adopt this, be careful to check for and programmatically close the dialog box when the task finishes. (Do this in the same area of the code as where you turn off the working hint and toggle the state of the various buttons.) Also, be careful to trigger the appearance of the dialog in the event dispatching thread. If you want (or need) to, you could put the "cancel" button on the resulting dialog box instead of on the main interface. (Although this demo does exactly that, I do not favor this approach, because it forces the user to wait at least as long as the expected timeout requires, and the user might be immediately sure they did something wrong.) Otherwise, just putting a simple message with an "Ok" button on the dialog serves its purpose: It lets the user know at least the UI portion of the application is alive and sympathetic to the user.
There you have it... a couple purpose-built helper classes, and a couple hooks added to a well-designed AppController class (you already have one, right?) and suddenly the management of all that spidery logic of a parallel task is contained. Even better, the UI stays responsive and the user is reassured that something is in fact happening. And when done correctly, the various concerns of the application are still relatively isolated from each other. Feel free to download the demo source code for this article to see everything strung together. (Remember the warning about needing 1.5 or higher to compile things as-is.) Applying this to your own tasks involves picking some sort of data object to wrap in the TaskInfo that will represent the task state (maybe a String will work, maybe you need your own custom object), and then writing your own Runnable implementation (or Thread subclass) that takes care to update the TaskInfo that is handed in.
It is worth noting that Java (as of 1.5) has a "concurrent" package. Although it has a wider range of utility than what this article has discussed, one interesting point is that there is a new Callable interface. It is conceptually similar to Runnable, except its sole implementation method call() returns a value (of generic type) and possibly throws a java.lang.Exception. (Runnable's run() does neither.) If you are interested in knowing whether all the above can be done using the java.util.concurrent classes, the answer is "possibly," but if you have existing Runnables or Thread subclasses, you'll likely face a bit of rewriting to take full advantage of everything the package provides: you'll probably end up using an ExecutorService to launch the Callable, and then dealing with a returned Future object, which you will still need to keep track of yourself. Still, it is a fairly interesting addition to the library that hasn't gotten a lot of press, so I thought I would mention it.
Download the Code
You can download the code that accompanies this article here.
About the Author
Rob Lybarger is a software guy (and a degreed aerospace engineer) in the Houston, TX area who has been using Java for nearly ten years. He has used various versions of Windows, various distributions of Linux, but loves Mac OS X. He likes exploring new techniques and new approaches to organizing and wiring applications, and loves to let the computer do as much work for him as possible.
Page 4 of 4