3

私は次のように持ってSwingWorkerいます:

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

Swing Worker上記を EDT から呼び出しました。

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

これでmainWorker、クラスの 10 個のインスタンスが作成MyTaskされ、各インスタンスが独自のスレッドで実行されるようになり、作業がより速く完了します。

しかし問題は、タスクの実行中に時々 GUI を更新したいということです。タスクがmainWorkerそれ自体で実行された場合、publish()およびprocess()メソッドを使用して GUI を更新できたことはわかっています。

しかし、タスクはスレッドとは異なるスレッドによって実行されるため、タスクを実行するスレッドSwingworkerによって生成された中間結果から gui を更新するにはどうすればよいですか。

4

4 に答える 4

8

SwingWorker の API ドキュメントには、次のヒントがあります。

このスレッドで doInBackground() メソッドが呼び出されます。これは、すべてのバックグラウンド アクティビティが発生する場所です。バインドされたプロパティの変更について PropertyChangeListeners に通知するには、firePropertyChange および getPropertyChangeSupport() メソッドを使用します。デフォルトでは、state と progress の 2 つのバインドされたプロパティを使用できます。

MainWorker実装できますPropertyChangeListener。その後、次のように自分自身を登録できますPropertyChangeSupport

getPropertyChangeSupport().addPropertyChangeListener( this );

MainWorkerPropertyChangeSupport作成するすべてのオブジェクトにそのオブジェクトを提供できMyTaskます。

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

MyTaskオブジェクトは、メソッドを使用して進行状況またはプロパティの更新を通知できMainWorkerますPropertyChangeSupport.firePropertyChange

MainWorkerそのように通知された は、EDT を介して Swing コンポーネントを使用SwingUtilities.invokeLaterまたは更新できます。SwingUtilities.invokeAndWait

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;
}
于 2010-05-13T19:45:23.617 に答える
3

SwingWorker を使用しない場合でも、SwingUtilities.invokeLater(...) または SwingUtilities.invokeAndWait(...) を使用して、EDT でやるべきことをいつでも投稿できます。

編集:いくつかのコードを実行するスレッドがあると仮定すると、以下の例のようにいつでも EDT と対話できます。

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
        }
    });
}
于 2010-05-09T11:58:21.957 に答える
2

を使用して複数のスレッドを起動する例を次に示します。SwingWorkerAは、すべてのスレッドが完了したときにのみ戻るCountDownLatchことを保証します。doInBackground()各スレッドは、スレッド セーフなappend()方法を使用JTextAreaして GUI を更新しEventQueue.invokeLater()ますが、便利な代替手段になります。

于 2010-05-13T22:10:07.067 に答える
0

これらの記事を読んで、問題を明確に把握してください

スレッドとスイング

Swing ワーカー スレッドの使用

Swing Threads の最後の言葉

于 2010-05-13T03:47:24.343 に答える