1

処理に数分かかるコードがあります。長い配列の文字列ごとにWebに接続する必要があり、各文字列はURLです。接続するたびにjtextareaを更新して、ユーザーが20分間フリーズしているように見える空白のページを見つめないようにする必要があります。またはそれがどれだけ長くかかるか。これは私が試したがうまくいかなかったものの例です:

try {
            ArrayList<String> myLinks = LinkParser.getmyLinksArray(jTextArea1.getText());
            for (String s : myLinks) {
                jTextArea2.append(LinkChecker.checkFileStatus(s) + "\n");
            }
        } catch (IOException ex) {
            JOptionPane.showMessageDialog(jTextArea1, "Parsing Error", "Parsing Error", JOptionPane.ERROR_MESSAGE);
            Logger.getLogger(MYView.class.getName()).log(Level.SEVERE, null, ex);
        }
4

3 に答える 3

10

問題は、計算を非同期で実行する必要があることです。計算を実行するバックグラウンドスレッドを作成してから、 SwingUtilities.invokeLaterを使用してJTextAreaを更新する必要があります。

final ArrayList <String> myLinks =//..。
(新しいスレッド()
{{
    public void run(){
        for(String s:myLinks){
            試す{
               最終的な文字列の結果=LinkChecker.checkFileStatus(s)+ "\ n";
               SwingUtilities.invokeLater(new Runnable(){
                    public void run(){    
                      jtextArea2.append(result);
                    }
                });
             } catch(IOExceptionエラー){
                //エラーを処理します
             }
        }
    }
})。始める();

編集
JTextAreaのappend関数は、実際にはスレッドセーフであることが指摘されています(ほとんどのSwing関数とは異なります)。したがって、この特定の場合、invokeLaterを介して更新する必要はありません。ただし、GUIを更新できるように、バックグラウンドスレッドで処理する必要があるため、コードは次のようになります。

final ArrayList <String> myLinks =//..。
(新しいスレッド()
{{
    public void run(){
        for(String s:myLinks){
            試す{
               jtextArea2.append(LinkChecker.checkFileStatus(s)+ "\ n");
             } catch(IOExceptionエラー){
                //エラーを処理します
             }
        }
    }
})。始める();

ただし、Swingオブジェクトを変更する他のほとんどの操作では、ほとんどすべてのSwing関数がスレッドセーフではないため、invokeLaterを使用する必要があります(変更がGUIスレッドで行われるようにするため)。

于 2010-04-26T02:10:21.827 に答える
1

スレッド化と、Swing でのGUI 更新との関係を調査する必要があります。Swing の GUI コンポーネントに影響を与えたり、GUI コンポーネントを使用したりすることは、イベント ディスパッチ スレッド (EDT)と呼ばれる特別なスレッドで行う必要があります。

コード スニペットが GUI をフリーズしている場合、EDT で実行されていると思います。EDT で実行時間の長いアクションを実行すると、GUI が応答しなくなります。これは、実行時間の長いプロセスがスレッドを使用している間は、それ以上の更新を行うことができないためです。

SwingWorker長時間実行される計算をバックグラウンド スレッドにオフロードし、完了時に GUI スレッドを更新できるようにするヘルパー クラスが呼び出されます。SwingWorkerコンテキストが GUI スレッドとバックグラウンド スレッドの間で切り替わるのを監視します。進行状況バーを表示して、長時間実行されているプロセスの状態をユーザーに知らせることもできます。これにより、ユーザーはアプリケーションがハングしていないことを知ることができます。

于 2010-04-26T02:14:26.480 に答える
0

swing / awtはシングルスレッドライブラリであるため、コンポーネントが表示された後は、外観を変更するだけでは正しく機能しません。スレッドからではなく、GUIスレッドでコンポーネントを変更する必要があります。これを行うには、SwingUtilities.invokeLater...でコンポーネントを更新するコードを次のようにラップします。

SwingUtilities.invokeLater(new Runnable()
{
    public void run()
    {
        jTextArea2.append(LinkChecker.checkFileStatus(s) + "\n");
    }
});

また、GUIが遅くなるのを防ぐために、GUIスレッドで行うことを制限したいので、checkFileStatusに時間がかかる場合は、runメソッドの外部で実行し、結果を最終的なローカル変数に格納して、 run()コード。

于 2010-04-26T02:09:09.417 に答える