简体   繁体   English

Java SwingWorker并发问题

[英]Java SwingWorker Concurrency Issue

I have a java program that does file manipulation and I have a GUI class that has a JTextArea that has console output redirected to it. 我有一个执行文件操作的Java程序,并且我有一个具有JTextArea的GUI类,该JTextArea的控制台输出已重定向到该类。 I am trying to get the SwingWorker in a different class to publish to that JTextArea but I can't seem to get it to work properly. 我正在尝试让SwingWorker在另一个类中发布到该JTextArea,但是我似乎无法使其正常工作。 In my GUI class, I have the following methods: 在我的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));
    }    

And then in my other class that does the work I have this: 然后在我做这件事的另一堂课中,我有以下内容:

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;
        }


}

Edit: here my process method: 编辑:这是我的处理方法:

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

This works sometimes but other times it completely skips over one of the publish() calls. 有时这可以工作,但有时却完全跳过了publish()调用之一。 For example, when it reaches publish("Setting restore point...") that would never actually show up on the JTextArea, and instead it would just skip over to "Applying Update..." 例如,当到达publish(“ Setting restore point ...”)时,它将永远不会真正显示在JTextArea上,而只是跳至“ Applying Update ...”。

How do I get this to publish and update the JTextArea exactly when I tell it to? 当我告诉它时,如何准确地发布和更新JTextArea?

publish(V... chunks) is used inside doInBackground() to send data to process(List<V> chunks) to process them in the GUI thread. doInBackground()内部使用publish(V... chunks)将数据发送到process(List<V> chunks)以在GUI线程中对其进行处理。 What you missed is overriding the process method: 您错过的是覆盖处理方法:

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

Don't publish or process anything. 请勿发布或处理任何内容。 In your situation since your JTextArea is receiving output redirected from System.out, it appears that all you have to do is call System.out.println(...) on the text that needs to be shown in the JTextArea. 在您的情况下,由于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;
    }
}

See code in this answer for a more complete example that includes use of a background thread. 有关包含后台线程使用的更完整的示例,请参见此答案中的代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM