I have a button, when the button is pressed, it calls wait on a thread and the GUI freezes when that call is made and I'm not sure why. In the process of trying to figure out what is going on, I have replaced the actual thread with a simple thread that is nothing more then a while(true) loop and I have tried a few ways of calling wait() all result in a frozen GUI.
Here is what the button does, Controller.getInstance().getScheduler() works fine and returns a thread without freezing, it is only when I call wait() that the GUI freezes.
And this is the thread I am trying to call wait on.
There are no other threads running that are trying to either use the EDT or the thread I am trying to wait, the thread doesn't do anything either so I'm at a bit of a loss.
I'm guessing you're calling wait() from the EDT, thereby placing the EDT on the wait list of the object returned by the getScheduler() call.
With no timeout specified for the wait() call or no call to notify() on the same object the EDT will forever be stuck in a WAITING state and never return to the RUNNABLE state.
As a result the GUI freezes completely.
Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.
Ok, so calling wait there is screwing things up, so I tried a SwingWorker, which does the job of avoiding a frozen gui, but fails to stop the other thread. I also tried another generic thread with the same result. I'm a little confused to say the least, what would be the correct way to call wait on a thread from within a gui.
will phillips wrote:Ok, so calling wait there is screwing things up, so I tried a SwingWorker, which does the job of avoiding a frozen gui, but fails to stop the other thread. I also tried another generic thread with the same result. I'm a little confused to say the least, what would be the correct way to call wait on a thread from within a gui.
Don't know what you mean by "stop the other thread". Maybe you should describe that to us?
Keep in mind, there is a reason why swing operations must be done in the event dispatching thread -- swing isn't thread safe, so all unsafe operations must be done in a particular thread. Unfortunately, there is only one event dispatching thread for everything in swing. This means that if you want to do complex operations, you shouldn't do it all in the EDT, because there is only one EDT. And at the same time, if you dispatch threads to do such operations to other threads, you need to understand when you need to dispatch back to the EDT.
For example, you should spin off complex DB or web services operations to separate thread, and this separate thread can wait() for results. But if those results needs to be displayed in swing, you need to dispatch that work back to the EDT.
I have several threads that run in the background, and one of them, the scheduler, changes the information displayed by the GUI. After so many changes occur, the scheduler will adds a little runnable object to the EDT(via invokeLater) that updates the required GUI elements, which works just fine and if that was all I was doing I could walk away. However, there are two situations where I would like to stop the changes from being made for a short period of time before resuming. One is to observe the current state of the information, the second opens a window that blocks the main GUI window and during the period where this second window is open I would like to stop changes from being made, just to make sure nothing is missed. So basically, I just want to pause the scheduler thread until it is told to resume.
So you should know that calling wait() does not pause the Object you call the method on, it makes the current Thread wait() for notification (effectively pausing) until notified by the same Object. Since you want the Scheduler to pause/wait you need to move the wait() call to the Scheduler thread. You then need to inform the Scheduler when it should pause and when it should continue. For example:
Then your button code (and the code that opens/closes the window would call