【问题标题】:Java SwingWorker Concurrency IssueJava SwingWorker 并发问题
【发布时间】:2013-11-05 17:10:25
【问题描述】:

我有一个执行文件操作的 java 程序,我有一个 GUI 类,它有一个 JTextArea,控制台输出重定向到它。我试图让 SwingWorker 在不同的类中发布到该 JTextArea 但我似乎无法让它正常工作。在我的 GUI 类中,我有以下方法:

public ShopUpdaterGUI() {
    initComponents();
    redirectSystemStreams();
}

private void updateTextArea(final String text) {
        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            consoleTextAreaInner.append(text);
          }
        });
}


private void redirectSystemStreams() {
      OutputStream out = new OutputStream() {
        @Override
        public void write(int b) throws IOException {
          updateTextArea(String.valueOf((char) b));
        }

        @Override
        public void write(byte[] b, int off, int len) throws IOException {
          updateTextArea(new String(b, off, len));
        }

        @Override
        public void write(byte[] b) throws IOException {
          write(b, 0, b.length);
        }
      };

      System.setOut(new PrintStream(out, true));
      System.setErr(new PrintStream(out, true));
    }    

然后在我的其他班级中,我有这个:

public void update(){
    (updateTask = new UpdateTask()).execute();
}

private class UpdateTask extends SwingWorker<Void, String>{

        @Override
        protected Void doInBackground() {
            try{
                publish("Creating backup...");
                mainBackup.createBackup();
                publish("Setting restore point...");
                setRestorePoint();
                publish("Applying update...");
                UPDHandler.unZipUpdate();
                saveModifiedFilesList();

            }catch(IOException ex){
                ex.printStackTrace();
            }catch(ClassNotFoundException ex){
                ex.printStackTrace();
            }finally{
                publish("Update Complete!");
            }

            return null;
        }


}

编辑:这里是我的处理方法:

    protected void process(List<String> updates){
        String update = updates.get(updates.size() - 1);
        System.out.println(update);
    }

这有时有效,但有时它会完全跳过其中一个 publish() 调用。例如,当它到达永远不会真正显示在 JTextArea 上的 publish("Setting restore point...") 时,它会直接跳到“Applying Update...”

我如何让它在我告诉它的时候准确地发布和更新 JTextArea?

【问题讨论】:

  • 您打算向我们展示您的publish() 方法的代码吗?
  • 虽然你从来没有回复过你上一个问题的答案,这让我想知道你是否阅读过答案,如果没有,为什么还要发布任何答案。

标签: java swing concurrency stdout swingworker


【解决方案1】:

publish(V... chunks)doInBackground() 内部使用,将数据发送到process(List&lt;V&gt; chunks) 以在GUI 线程中处理它们。您错过的是覆盖 process 方法:

@Override
 protected void process(List<String> chunks) {
     for (String s : chunks) {
         textArea.append(s + "\n");
     }
 }

【讨论】:

    【解决方案2】:

    不要发布或处理任何内容。在您的情况下,由于您的 JTextArea 正在接收从 System.out 重定向的输出,看来您所要做的就是在需要在 JTextArea 中显示的文本上调用 System.out.println(...)

    private class UpdateTask extends SwingWorker<Void, String>{
    
        @Override
        protected Void doInBackground() {
            try{
                publish("Creating backup...");
                mainBackup.createBackup();
    
                // publish("Setting restore point...");
                System.out.println("Setting restore point...");
    
                setRestorePoint();
    
                // publish("Applying update...");
                System.out.println("Applying update...");
    
                UPDHandler.unZipUpdate();
                saveModifiedFilesList();
    
            }catch(IOException ex){
                ex.printStackTrace();
            }catch(ClassNotFoundException ex){
                ex.printStackTrace();
            }finally{
                publish("Update Complete!");
            }
    
            return null;
        }
    }
    

    请参阅this answer 中的代码以获取包含使用后台线程的更完整示例。

    【讨论】:

      猜你喜欢
      • 2011-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-10
      • 1970-01-01
      • 1970-01-01
      • 2019-04-13
      相关资源
      最近更新 更多