2011-07-30 37 views
6

我試圖用的SwingWorker與結果進行冗長的任務和更新的JLabel:的Java GUI凍結甚至SwingWorker的

button.addActionListener(new ActionListener() { 

    @Override 
    public void actionPerformed(ActionEvent arg0) { 
     new SwingWorker<String, Void>() { 

      @Override 
      protected String doInBackground() throws Exception { 
       return doCalculation(); 
      } 

      protected void done() { 
       try { 
        label.setText(get()); 
       } catch (InterruptedException e) { 
        System.out.println("thread was interrupted"); 
       } catch (ExecutionException e) { 
        System.out.println("there was an ExecutionException"); 
       } 
      } 

     }.execute(); 

    } 

}); 

我可以單擊該按鈕多次,因爲我喜歡和GUI將保持響應,直到兩個線程完成,此時Gui在線程運行時凍結。如果我一次只運行一個線程,這個問題仍然會發生。

如果有人能指出我是否錯誤地使用了SwingWorker,或者如果有另一個我不知道的問題,我會很感激。謝謝你的時間。 伊恩

編輯

的doCalculation()是隻是一些耗時:

private String doCalculation() { 
    for (int i = 0; i < 10000000; i++) { 
     Math.pow(3.14, i); 
    } 
    return threads++ + ""; 
} 
+1

到目前爲止,我沒有發現任何明顯錯誤的代碼,但我認爲這裏的關鍵是'doCalculation();'方法中發生了什麼。你能發佈這個代碼嗎? –

回答

6

我很抱歉,但即使你的doCalculate()方法,我還是沒能重現您的問題。例如,下面是我的sscce

import java.awt.event.*; 
import java.util.concurrent.ExecutionException; 
import javax.swing.*; 

public class FooGui { 
    private static int threads = 0; 

    private static void createAndShowUI() { 
     final JLabel label = new JLabel("  "); 
     JButton button = new JButton("Button"); 
     button.addActionListener(new ActionListener() { 

     @Override 
     public void actionPerformed(ActionEvent arg0) { 
      new SwingWorker<String, Void>() { 

       @Override 
       protected String doInBackground() throws Exception { 
        return doCalculation(); 
       } 

       @Override 
       protected void done() { 
        try { 
        label.setText(get()); 
        } catch (InterruptedException e) { 
        System.out.println("thread was interrupted"); 
        } catch (ExecutionException e) { 
        System.out.println("there was an ExecutionException"); 
        } 
       } 
      }.execute(); 
     } 
     }); 
     JPanel panel = new JPanel(); 
     panel.add(button); 
     panel.add(label); 

     JFrame frame = new JFrame("FooGui"); 
     frame.getContentPane().add(panel); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    private static String doCalculation() { 
     for (int i = 0; i < 5000000; i++) { 
     Math.pow(3.14, i); 
     } 
     return threads++ + ""; 
    } 

    public static void main(String[] args) { 
     java.awt.EventQueue.invokeLater(new Runnable() { 

     @Override 
     public void run() { 
      createAndShowUI(); 
     } 
     }); 
    } 
} 

您可能希望創建併發布自己的"Short, Self Contained, Correct (Compilable), Example" or SSCCE(請鏈接)。我敢打賭,在創建這個過程中,你可能會自己發現問題和解決方案。如果是這樣,請務必回到這裏告訴我們。

我知道這不是一個真正的答案,但是沒有辦法在評論中發佈這樣的代碼。

+1

謝謝你的幫助,我很感激。我在你的例子中發現了同樣的凍結,所以我嘗試了它。從eclipse /命令行運行再現了這一點。我創建了一個可運行的jar,它運行完美。我正在運行64位Windows 7.我在Ubuntu上試過,似乎也解決了這個問題。再次感謝。 – Ian

+0

我從來沒有看到裏面的聽衆,我不知道把...,但你的帖子,這可能是可能的方式,很好的例子,沒有性能問題+1 – mKorbel

+1

@伊恩:嗯,這仍然是很好的知道爲什麼在某些情況下會發生凍結。也許這與線程太多有關。我聽說有時在處理多線程時不能使用SwingWorker,而是需要使用ExecutorService和線程池。 –