Hi All,
I have a multi-threaded application. Within the application is a series
of functions that are called through a socketed interface that handle
some rather time consuming operations. There is a hand shaking protocol
that allows the top level GUI to know when the low level software has
completed the functionality, and I've implemented a JProgressBar to show
the user how far along int he process these functions are.
Unfortunately, the GUI will not update for me. I've tried everything
from repaint()/revalidate() to using a Timer to using Thread.yield(...)
and Thread.sleep(...). The user selects a file from a standard file
chooser dialog, and once the file has been selected the file chooser
dialog closes but the GUI beneath it does not redraw the area over which
the file chooser dialog was placed. Following, the progress bar should
be updated periodically as new messages are received back from the low
level software indicating a portion of the work is completed. The low
level functionality is not all written in Java, and there are more than
just two threads involved here, but I'm sure this should be doable somehow.
The basic flow is like this:
1. GUI informs low level S/W to execution some function.
2. Low level S/W sends periodic updates while the GUI waits on some
already known condition to be met indicating the operation is complete.
3. GUI continues on its merry way.
The wait loop in the GUI software looks like this:
timer.start();
while( curTimerLoc < finalTimerLoc ) {
msg = DbgSocket.requestMessage();
if( msg != null ) {
curTimerLoc = msg.lastOffset;
}
}
I currently have a timer implemented that should update the progress bar:
timer = new Timer( 1000, new ActionListener() {
public void actionPerformed( ActionEvent evt ) {
System.out.println( "tick!" );
dbgProg.updateProgressBar( curTimerLoc );
if( curTimerLoc >= finalTimerLoc ) {
dbgProg.setMessage( "Ready" );
timer.stop();
}
}
});
UpdateProgressBar looks like this:
public void updateProgressBar( int curLoc ) {
progressBar.setValue( curLoc );
}
The "tick!" message I have in the timer is displayed only one time
during execution currently, and that's after the time consuming
operation has completed. I got the timer idea from reading the Java
tutorials on this very subject, but it still doesn't work for me.
Any help would be greatly appreciated.
Cheers,
Jeremy
xarax - 07 Jan 2005 04:51 GMT
=============================================
Hi All,
I have a multi-threaded application. Within the application is a series of
functions that are called through a socketed interface that handle some rather
time consuming operations. There is a hand shaking protocol that allows the top
level GUI to know when the low level software has completed the functionality,
and I've implemented a JProgressBar to show the user how far along int he
process these functions are.
Unfortunately, the GUI will not update for me. I've tried everything from
repaint()/revalidate() to using a Timer to using Thread.yield(...) and
Thread.sleep(...). The user selects a file from a standard file chooser dialog,
and once the file has been selected the file chooser dialog closes but the GUI
beneath it does not redraw the area over which the file chooser dialog was
placed. Following, the progress bar should be updated periodically as new
messages are received back from the low level software indicating a portion of
the work is completed. The low level functionality is not all written in Java,
and there are more than just two threads involved here, but I'm sure this should
be doable somehow.
The basic flow is like this:
1. GUI informs low level S/W to execution some function.
2. Low level S/W sends periodic updates while the GUI waits on some already
known condition to be met indicating the operation is complete.
3. GUI continues on its merry way.
The wait loop in the GUI software looks like this:
timer.start();
while( curTimerLoc < finalTimerLoc ) {
msg = DbgSocket.requestMessage();
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^ Your GUI thread is suspended here. ^^
if( msg != null ) {
curTimerLoc = msg.lastOffset;
}
}
I currently have a timer implemented that should update the progress bar:
timer = new Timer( 1000, new ActionListener() {
public void actionPerformed( ActionEvent evt ) {
System.out.println( "tick!" );
dbgProg.updateProgressBar( curTimerLoc );
if( curTimerLoc >= finalTimerLoc ) {
dbgProg.setMessage( "Ready" );
timer.stop();
}
}
});
UpdateProgressBar looks like this:
public void updateProgressBar( int curLoc ) {
progressBar.setValue( curLoc );
}
The "tick!" message I have in the timer is displayed only one time during
execution currently, and that's after the time consuming operation has
completed. I got the timer idea from reading the Java tutorials on this very
subject, but it still doesn't work for me.
Any help would be greatly appreciated.
=============================================
Your problem is caused by suspending the GUI thread
waiting for a message from DbgSocket.requestMessage().
Whatever thread is posting a message to DbgSocket,
it should instead call SwingUtilities.invokeLater(Runnable)
to update the offset. Get rid of that wait loop in the GUI.
Jeremiah Frick - 07 Jan 2005 14:08 GMT
Thanks for the response!
The problem is that the thread that is actually posting the response to
the DbgSocket is not a Java thread, it's a C thread, so I can't have it
spawn a Java invokeLater routine.
Also, even though I know the GUI is deadlocked while it's in that wait
loop, I also know it receives the messages on a periodic basis as I've
added debug printouts to verify that the messages are being received.
What I don't understand is why I can't update the GUI in the while loop
after the GUI thread receives the message via the DbgSocket and before
it waits for the next message.
Jeremy
>=============================================
>Hi All,
[quoted text clipped - 68 lines]
>it should instead call SwingUtilities.invokeLater(Runnable)
>to update the offset. Get rid of that wait loop in the GUI.
xarax - 07 Jan 2005 19:26 GMT
Have another thread wait for the message. Don't wait
in the GUI thread. The GUI thread is event driven.
Updates to the visual components must go through
the entire event loop cycle.
So, just have a different Java thread wait on DbgSocket,
and it will post updates to the GUI thread using the
invokeLater() method.
> Thanks for the response!
>
[quoted text clipped - 83 lines]
> >it should instead call SwingUtilities.invokeLater(Runnable)
> >to update the offset. Get rid of that wait loop in the GUI.
Jeremiah Frick - 07 Jan 2005 22:24 GMT
xarax,
Thanks again!
I moved all of the wait source to a new thread that's spawned when
required and exits when the wait condition is met, effectively. I still
use a timer to actually perform the GUI update; all the thread does
really is update the member variables that the update is based
on...anyway, it works perfectly now.
Thanks so much for your help.
Jeremy
>Have another thread wait for the message. Don't wait
>in the GUI thread. The GUI thread is event driven.
[quoted text clipped - 116 lines]
>>>it should instead call SwingUtilities.invokeLater(Runnable)
>>>to update the offset. Get rid of that wait loop in the GUI.