2009-06-02 13 views
11

私は、オブジェクトのリストを格納するスイングアプリケーションを持っています。ユーザーがボタンをクリックすると、バックグラウンドタスク中にSwing GUIがロックされないようにする

リスト内の各オブジェクトに対して2つの操作を実行してから、完了したら結果をJPanelでグラフ化します。私はSwingWorker、Callable & Runnableを処理しようとしていましたが、リストの処理中(IOバインドに数分かかることがあります)には、何をしていてもGUIはロックされています。

私はそれがおそらくスレッドや何かを呼び出す方法だと感じていますか、それともグラフ機能と関係がありますか?それは非常に速いので、スレッドされていません。

私も2つの処理段階を順番に行う必要があります。したがって、2番目の処理段階が最初に待っていることを確認する最も良い方法は何ですか?私は)(参加使ってきたし、その後

while(x.isAlive()) 
{ 
     Thread.sleep(1000); 
} 

は試してみて、これを確実にするために、私は、これはあまりにも私の問題の原因である可能性が心配です。

私はどこでもポインタを探していましたが、何も見つからないので、ここで何か愚かなことをしていると確信しています。

+2

SwingWorkerをどのように使用しているかを示すコードを含めると役立ちます。 –

+0

同意。問題のあるコードを表示してください。 – Rob

答えて

18

問題は、長時間実行されているタスクがGUIを応答可能にするスレッドをブロックしていることです。

実行する必要があるのは、長時間実行されているタスクを別のスレッドに置くことです。

これを行う一般的な方法は、タイマーまたはSwingWorkerを使用する方法です。

Java tutorialsには、これらのことがレッスンの並行性に関して多くの情報を持っています。

第1のタスクが第2のタスクの前に終了することを確認するには、両方を同じスレッドに入れてください。そうすれば、2つの異なるスレッドを正確に計時することを心配する必要はありません。ここで

はSwingWorkerForあなたの例のサンプルの実装です:

public class YourTaskSwingWorkerSwingWorker extends SwingWorker<List<Object>, Void> { 
    private List<Object> list 
    public YourClassSwingWorker(List<Object> theOriginalList){ 
     list = theOriginalList; 
    } 

    @Override 
    public List<Object> doInBackground() { 
     // Do the first opperation on the list 
     // Do the second opperation on the list 

     return list; 
    } 

    @Override 
    public void done() { 
     // Update the GUI with the updated list. 
    } 
} 

リストを変更するイベントが発生したときに、このコードを使用する新しいSwingWorkerを作成して開始することを伝えるために。

+1

私はかなりの質問スレッドとSwingWorkerを既に言及していると確信しています。また、SwingUtilities.invokeLater()はGUIスレッド上で動作します。 – Powerlord

+0

ええ、私はまあまあの一般的なスイングスレッドの答えを与えた...ちょっと吸う – jjnguy

+0

ここでは、ええ、私はそれらの提案をすでに試してみましたが、私はそれらを正しく実装していない可能性があります...私はスイングチュートリアルそれはスイングワーカーにはあまりありません。少なくとも、私が従っている情報ではありません。 – Simonw

5

スイングスレッドを正しく戻していません。私はあなたがコール可能/実行可能ファイルを使用していることを認識していますが、私はあなたがそれを正しくやっていないと推測しています。

基本的な構造は次のようになります。

swingMethod() { // Okay, this is a button callback, we now own the swing thread 
    Thread t=new Thread(new ActuallyDoStuff()); 
    t.start(); 
} 

public class ActuallyDoStuff() implements Runnable { 
    public void run() { 
     // this is where you actually do the work 
    } 
} 

これはちょうど私の頭の上からですが、私はあなたがどちらかthread.startをしていない、代わりにrunメソッドを呼び出していることを推測していますそれをロックする最初のメソッド(thread.joinなど)で何か他のことをやっています。これらのどちらもスイングスレッドを解放しません。最初のメソッドはすばやく返さなければならず、run()メソッドは必要なだけ時間がかかります。

最初のメソッドでthread.joinを実行している場合、そのスレッドはシステムに戻されていません!

編集:(実際には第2の編集) 私はあなたが実際に感じている問題に話すと思います。モデル/ビュー/コントローラーシステムに関してもっと考えてみてください。あなたが書いているコードはコントローラです(ビューは一般的に画面上のコンポーネントとみなされます - ビュー/コントローラは通常非常に緊密にバインドされています)。

コントローラがイベントを取得すると、コントローラはイベントをモデルに渡します。ビューは、その後、画像から外れています。それはモデルを待つことはなく、ただ完了しました。

モデルが完成したら、コントローラに何か他のことをさせる必要があります。これは、invokeメソッドの1つを使用して行います。これはコントローラーに制御を戻し、あなたは元気に進みます。このように考えると、コントロールを分離して意図的に前後に渡しても、かさばることはありません。このようにするのは実際には非常に一般的です。

+0

私の場合、私はthread.start()の代わりにthread.run()を実行していたので、GUIのロックにつながった。 thread.start()を設定すると問題が解決しました。 – Alexey

1

GUIスレッドの内部からスレッドが終了するのを待っている可能性があります。 GUIスレッドはこれらのスレッドを待つべきではなく、ワーカースレッドがフラグを設定するGUIスレッド上で何らかのメソッドを呼び出さなければなりません。両方のフラグが設定されていると、両方のスレッドが終了し、グラフを作成できることがわかります。

0

私は本当にスイングスレッドモデルに話すことはできませんが、私はあまりにもために、2つの処理段階を行う必要があり

ので、二つ上の待っていることを確認するための最良の方法は何ですか最初?

この種の機能性については、2つのワーカースレッドを作成し、JMSブローカーを組み込むことをお勧めします。読み取ったJMSキューにメッセージを渡すことによって、2つのスレッドに作業を配信します。あなたのGUIスレッドはキューを調べて、いつ仕事が起きているかを判断し、あなたのUIでのプレイの状態を表現することができます。

0

私の問題の解決策は、jjnguyとBill Kの回答が混在していたので、その人たちには非常に感謝しています。私はこのようなSwingWorkerの内のスレッドを使用するために必要な:

public class Worker extends SwingWorker<Void, Void> 
{ 
    private List<Object> list; 
    public YourClassSwingWorker(List<Object> theOriginalList){ 
     list = theOriginalList; 
    } 

    @Override 
    public List<Object> doInBackground() { 
     Thread t = new Thread(new ProcessorThread(list)); 
     t.start(); 
    } 

    @Override 
    public void done() { 
     // draw graph on GUI 
    } 
} 
class ProcessorThread implements Runnable { 
    //do lots of IO stuff 
    Thread t2 = new Thread(new SecondProcess()); 
    t2.start(); 
} 

これは、すべての作業が離れGUIからワーカースレッドによって行われていたことを確認した、ともSwingWorkerの自体は、すべての作業をしていなかったことを確実にしますこれは問題であった可能性があります。

+3

Whoa whoa whoa!なぜあなたはSwingWorkerからスレッドを生成していますか? SwingWorkers(execute()メソッドで起動されたとき)はGUIスレッド上では実行されないため、ここに別のスレッドを作成する必要はありません。 –

+0

これは私にとってうまくいった唯一の解決策だったので、最初は間違っていたに違いない – Simonw

関連する問題