> And you'll end up with a highly user hostile application.
> [..]
>
[quoted text clipped - 3 lines]
> trying to do before was the exact same thing, I just didn't
> realize that there's already a class for that.
The trouble is that you lock up the rest of your world whilst a single
window appears. Not something you want to do if your aim is maintain any
kind of usability. There is no point in writing such applications.
> Can you please explain your code a bit? I don't understand
> what it does and how it solves the problem...
This is a GUI centric way of doing things. Slightly different from what
you described, which I'll explain at the bottom (if I remember...).
We assume this is called from some GUI event handler. All GUI
processing, including event handlers, should be done in the same thread
known as the Event Dispatch Thread (EDT). We put in asserts both to
remind the programmer from which thread it should be called, and to
check that we are doing it right.
The goal is to put the long running tasks outside of the EDT so the GUI
doesn't freeze. Long running task may be computational or involve
network connections.
> private void somethingLong(String arg) {
> assert EventQueue.isDispatchThread(); // In EDT
This just sets up and runs our task that should run in response to the
event.
> Thread thread = new Thread(new Runnable() {
> public void run() {
[quoted text clipped - 7 lines]
> }
> setStatusLater(result+arg);
This last call is to push the results back to the GUI.
> }
> }), "Something long");
> thread.setPriority(Thread.NORM_PRIORITY); // 1 less than EDT
> thread.setDaemon(true);
> thread.start();
That's off and running. We almost instanteously return to the GUI, so
that it feels responsive.
> }
> private void setStatus(String message) {
> assert !EventQueue.isDispatchThread(); // Outside EDT
This method is going to reflect changes from our non-GUI task into our
GUI. In this case it's just changing a status message, but could do
something more complicated involving more data.
> // If we call this repeatedly the GUI wont have a fit.
> synchronized (this) {
> statusMessage = message;
> }
Both our task thread and EDT are going to access the statusMessage
variable, so it needs to be synchronised. Here we update it for the next
update GUI task to update the actual GUI component.
> EventQueue.invokeLater(new Runnable() {
> public void run() {
[quoted text clipped - 4 lines]
> }
> statusLabel.setText(statusMessage);
This code will run in the EDT sometime later and do the GUI updating. We
could have used a final variable from the enclosing method rather than
the synchronised member variable. However this has the advantage that if
I was updating progress, say, then if the non-GUI thread did thousands
of updates while the EDT was busy, then only the last update does any
real GUI work. Otherwise we'd have the GUI revalidating and repainting
itself for each of the thousands of out of date states.
> }
> });
> }
I think the original problem was phrased to imply a solution where there
would be another main thread running the show. This is how DOS programs
tended to work. It doesn't make a great fit for GUIs. You can do it, but
in order not to compromise usability takes some effort. With more than
one GUI component where is your thread going to be waiting? It all gets
very complicated.
Tom Hawtin

Signature
Unemployed English Java programmer
http://jroller.com/page/tackline/