[jarp-developer] Swing and threads
Brought to you by:
ricardo_padilha
From: Filip L. <fil...@ma...> - 2001-01-28 22:09:07
|
Hi, After browsing through the existing petri net analysis code (e.g. PetriStatesEnumAnalysis.java) I have the following comments: Swing is not thread-safe, so only one thread should update or call Swing components, unless the method in question explicitely is documented as reentrant. After initialization, the dispatcher thread is the thread that is calling all the Listeners registered for the various components, and as a rule of thumb, only this thread should call Swing components. Other threads can place small "jobs" in the Swing event queue by registering a Runnable with the javax.swing.SwingUtilities.invokeAndWait (for synchronous updates) and .invokeLater (for asynchronous updates) methods. To track the status of work going on in another thread, one normally registers via invokeLater a Runnable that queries the status of the work, updates the gui, waits a while and then register itself again if the thread is still working. To get the result after work is done in case the result is not updated like above, the working thread can use invokeLater to register a runnable to update the work just once. The following outline should illustration what I mean (without exception handling, though, and with one gui for both status and result): public class MyAnalyzer { class Task implements Runnable { public Task(Runnable onCompletion) { this.onCompletion = onCompletion; } public void stop() { interrupted = true; } public boolean isRunning() { return working; } public boolean wasInterrupted { return interrupted; } public void run() { // invoked in work thread while (working && !interrupted) { doWork(); } working = false; if ( onCompletion != null ) SwingUtilities.invokeLater(onCompletion); } public Object getStatus() { ... } public Object getResult() { ... } private boolean working = true; private boolean interrupted = false; private Runnable onCompletion = null; private void doWork() {{ // invoked in work thread ... if ( done ) working = false; ... } } public void execute() { // invoked in dispatcher thread makeGui(); startTask(); registerStatus(); } private Task task = new Task(); private Component gui; private void makeGui() { gui = new ...; JButton stopButton = ... stopButton.addActionListener( new ActionListener() { public void actionPerformed() { if ( task != null ) task.stop(); } }); } private void registerStatus() { SwingUtilities.invokeLater( new Runnable() { public void run() { // invoked in dispatcher thread gui.setStatus( task.getStatus() ); Thread.sleep(1000); if ( task.isRunning() ) SwingUtilities.invokeLater(this); } }); } private void startTask() { Runnable onCompletion = new Runnable() { public void run() { // invoked in dispatcher thread stopButton.setEnable(false); if ( task.wasInterrupted() ) gui.setStatus(task.getStatus()); else gui.setResult(task.getResult()); task = null; } } task = new Task( onCompletion ); Thread t = new Thread( task ); t.run(); } } BR, --- Filip Larsen <fil...@ma...> |