SwingのGUIを防ぐため、バックグラウンドタスク中にロックアップ
-
06-09-2019 - |
質問
私は、オブジェクトのリストを格納スイングアプリケーションを持っています。ユーザーがボタンをクリックすると、
私は、リスト内の各オブジェクト上の2つの操作を実行したい、そしてそれが完了すると、のJPanelで結果をグラフ化。私は、処理を行うにはSwingWorkerの、呼び出し可能&Runnableををしようとしてきたが、(それはIOがバインドされているように、数分かかることがあります)、リストの処理中に関係なく、私は何をすべきか、GUIがロックされています。
私はそれはおそらく私がスレッドや何かを呼んでいる方法です感じている、またはそれは、グラフ作成機能をどうするだろうか?それは非常に迅速であるとしてそれはスレッド化されていません。
私もために、2つの処理段階をしなければならないので、二番目のは、最初に待っていることを確認するための最良の方法は何ですか?私は()に参加して、
を使用しましたwhile(x.isAlive())
{
Thread.sleep(1000);
}
これを試してみて確保するために、私は、これはあまりにも私の問題の原因である可能性が心配です。
私はいくつかのポインタのためにどこでも見てきたが、私はいずれかを見つけることができないので、私はここに愚かな何かをやっていると確信しています。
解決
問題は、あなたの実行時間の長いタスクが応答GUIを維持スレッドをブロックしているされます。
あなたが別のスレッドで実行時間の長いタスクを入れて行う必要がありますどのような。
これを行うためのいくつかの一般的な方法は、タイマーや<のhref =「http://java.sun.com/javase/6/docs/api/javax/swing/SwingWorker.html」のrel =「noreferrer」を使用しています> SwingWorker
でます。
他のヒント
あなたは正しくスイングスレッドを返されていません。私はあなたが実行可能/呼び出し可能使用しているが、私は(あなたは確実に知るために十分なコードを投稿しませんでしたが)あなたは右のそれをやっていない推測して実現します。
基本的な構造は以下のようになります:
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を行っている場合は、、その後、スレッドはシステムに戻されていません!
編集:(実際には第二編集) あなたは、モデル/ビュー/コントローラシステムの面でより多くを考えたいかもしれない - 私はあなたが実際に感じている問題に話をすると思います。あなたが書いているコードは、コントローラ(ビューは、一般的に画面上のコンポーネントであると考えられている - ビュー/コントローラは、通常、非常に緊密に結合している)である。
あなたのコントローラーがイベントを取得すると、それはあなたのモデルを切る作業を渡す必要があります。ビューには、絵の外に、その後です。それはそれはちょうど行うのは、モデルを待ちません。
お使いのモデルが終了したら、、それは、何かを行うには、コントローラに通知する必要があります。それがinvokeメソッドの1つを介してこれを行います。これは、バックコントローラに制御を移し、あなたの陽気の道を行きます。あなたはそれほどかさばる感じていない前後にそれを渡して、意図的にコントロールを分離し、このようそれについて考え、そしてそれは、このようにそれを行うには実際には非常に一般的です場合ます。
これが鳴ります。あなたのGUIスレッドは、これらのスレッドを待つべきではない代わりに、あなたは、ワーカースレッドがフラグを設定するGUIスレッドにいくつかのメソッドを呼び出す必要があります。両方のフラグが設定されているとき、あなたは両方のスレッドが終了し、グラフを行うことができます知っています。
私は実際にスイングスレッドモデルに話すことはできませんが、ます:
私もために、2つの処理段階をしなければならないので、二番目のは、最初に待っていることを確認するための最良の方法は何ですか?
この種の機能のために、私はあなたが2つのワーカースレッドを作成して提案、およびJMSブローカーを埋め込むと思います。彼らはから読み取るJMSキューにメッセージを渡すことにより、2つのスレッドに仕事を提供します。あなたのGUIスレッドは仕事が起こっている場合を決定し、あなたのUIでのプレイの様子を表現するためにキューを調べるために自由である。
私の問題を解決するには、jjnguyとビル・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の自体が問題だったかもしれない仕事のすべてをやっていなかったことを確実にされていたことを確認しました。