Java - SwingWorker - Can we call one SwingWorker from other SwingWorker instead of EDT

牧云@^-^@ 提交于 2019-12-09 07:13:08

问题


I have a SwingWorker as follows:

public class MainWorker extends SwingWorker(Void, MyObject) {
    :
    :
}

I invoked the above Swing Worker from EDT:

MainWorker mainWorker = new MainWorker();
mainWorker.execute();

Now, the mainWorker creates 10 instances of a MyTask class so that each instance will run on its own thread so as to complete the work faster.

But the problem is I want to update the gui from time to time while the tasks are running. I know that if the task was executed by the mainWorker itself, I could have used publish() and process() methods to update the gui.

But as the tasks are executed by threads different from the Swingworker thread, how can I update the gui from intermediate results generated by threads executing tasks.


回答1:


The SwingWorker's API documentation offers this hint:

The doInBackground() method is called on this thread. This is where all background activities should happen. To notify PropertyChangeListeners about bound properties changes use the firePropertyChange and getPropertyChangeSupport() methods. By default there are two bound properties available: state and progress.

MainWorker can implement PropertyChangeListener. It can then register itself with its PropertyChangeSupport:

getPropertyChangeSupport().addPropertyChangeListener( this );

MainWorker can supply its PropertyChangeSupport object to every MyTask object it creates.

new MyTask( ..., this.getPropertyChangeSupport() );

A MyTask object can then notify its MainWorker of progress or property updates by using PropertyChangeSupport.firePropertyChange methods.

MainWorker, so notified, can then use SwingUtilities.invokeLater or SwingUtilities.invokeAndWait to update the Swing components via the EDT.

protected Void doInBackground() {
    final int TASK_COUNT = 10;
    getPropertyChangeSupport().addPropertyChangeListener(this);
    CountDownLatch latch = new CountDownLatch( TASK_COUNT ); // java.util.concurrent
    Collection<Thread> threads = new HashSet<Thread>();
    for (int i = 0; i < TASK_COUNT; i++) {
        MyTask task = new MyTask( ..., latch, this.getPropertyChangeSupport() ) );
        threads.add( new Thread( task ) );
    }
    for (Thread thread: threads) {
        thread.start();
    }
    latch.await();
    return null;
}



回答2:


Even if you do not use SwingWorker, you can always post things to do in the EDT using SwingUtilities.invokeLater(...) or SwingUtilities.invokeAndWait(...)

EDIT: suppose that you have a thread executing some code, you can always interact with EDT like in the example below.

public void aMethodExecutedInAThread() {

    // Do some computation, calculation in a separated Thread

    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            // Post information in the EDT
            // This code is executed inside EDT
        }
    });
}



回答3:


Here is an example that uses a SwingWorker to launch multiple threads. A CountDownLatch ensures that doInBackground() returns only when all threads have completed. Each thread uses the thread-safe append() method of JTextArea to update the GUI, but EventQueue.invokeLater() would be a convenient alternative.




回答4:


Read these artcles to get a clear picture of your problem

Threads and Swing

Using a Swing Worker Thread

The last word in Swing Threads



来源:https://stackoverflow.com/questions/2797483/java-swingworker-can-we-call-one-swingworker-from-other-swingworker-instead

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!