【问题标题】:JAVA - Why SwingWorker Thread not processing all publish strings?JAVA - 为什么 SwingWorker 线程不处理所有发布字符串?
【发布时间】:2017-08-20 13:06:57
【问题描述】:

我正在使用一个扩展SwingWorker 的Worker 类,并在它的process 方法中处理String 值并将它们打印到JTextArea

所以我做了很多 publish(some_string) 调用来将字符串打印到文本区域,但是当我执行我的工作线程时 - 它不会打印我在doInBackground() 方法。它错过了很多发布调用,我只得到了我想要的部分单词。

但是当我执行线程并放置一个断点一步一步地跟随它我可以看到它确实打印了发布调用中的所有字符串
做该做的事。

为什么它在调试模式下工作,而在正常模式下却不行?

我的代码:

public class Worker extends SwingWorker<Void , String>
{
    public Worker(int int optionOfWork){};

    protected Void doInBackground() throws Exception
    {
        ...
        publish("Hellow");
        publish("This is a test");
        ...
        //  a lot of **publish(some_word) calls**   
        ... 
        publish("Some more words");

    }//doInBackground()


    @override
    protected void process(List<String> wordsToPrint)
    {
        String lastWordRecieved = wordsToPrint.get(wordsToPrint.size()-1);
        mainWindowTextArea.append(lastWord);  // not printing\appending all the words sent here by the publish calls
    }


    @override
    protected void done()
    {
        publish("\nDone");
    }

}//Worker class  

我在主线程中所做的只是创建一个 Worker 对象并执行它:

Worker worker = new Worker();

我使用worker.excute();启动它

【问题讨论】:

  • 请创建并发布一个有效的minimal reproducible example,我们可以编译和运行的代码向我们展示您的问题。
  • 请查看编辑以回答。询问是否有任何令人困惑的地方。

标签: java multithreading swing jtextarea swingworker


【解决方案1】:

改变这个:

@override
protected void process(List<String> wordsToPrint)
{
    String lastWordRecieved = wordsToPrint.get(wordsToPrint.size()-1);
    mainWindowTextArea.append(lastWord);  // not printing\appending all the words sent here by the publish calls
}

    @override
protected void done()
{
    publish("\nDone");
}

到这里:

@override
protected void process(List<String> wordsToPrint) {
    for (String text: wordsToPrint) {
        mainWindowTextArea.append(text + "\n");
    }
}

@override
protected void done() {
    publish("\nDone");
    try {
        get();
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    }
}  

for循环一般是你如何通过传递给process方法的String列表进行处理的。不要忘记在 SwingWorker 上调用 get(),如果只是为了检查是否引发了任何异常。如果仍然卡住,那么是的,创建并发布 mcve

您可能需要在 publish(...) 调用之间放置一些 Thread.sleep(10) 以防止调用占用 CPU。

例如:

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import javax.swing.*;

@SuppressWarnings("serial")
public class SwingWorkerExample extends JPanel {
    private JTextArea textArea = new JTextArea(30, 40);
    private MyWorker myWorker;

    public SwingWorkerExample() {
        textArea.setFocusable(false);
        JScrollPane scrollPane = new JScrollPane(textArea);
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

        JPanel bottomPanel = new JPanel();
        bottomPanel.add(new JButton(new AbstractAction("Start Worker") {

            @Override
            public void actionPerformed(ActionEvent e) {
                if (myWorker != null && !myWorker.isDone()) {
                    myWorker.setLoopRunning(false);
                }

                myWorker = new MyWorker();
                myWorker.execute();
            }
        }));
        bottomPanel.add(new JButton(new AbstractAction("Stop Worker") {

            @Override
            public void actionPerformed(ActionEvent e) {
                if (myWorker != null && !myWorker.isDone()) {
                    myWorker.setLoopRunning(false);
                }
            }
        }));

        setLayout(new BorderLayout());
        add(scrollPane);
        add(bottomPanel, BorderLayout.PAGE_END);
    }

    private class MyWorker extends SwingWorker<Void, String> {
        private volatile boolean loopRunning = true;

        @Override
        protected Void doInBackground() throws Exception {
            for (int j = 0; j < 1000 && loopRunning; j++) {
                for (int i = 0; i < 1000 && loopRunning; i++) {
                    String text = String.format("My Text %03d", i);
                    publish(text);
                    TimeUnit.MILLISECONDS.sleep(10);
                }
            }
            return null;
        }

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

        @Override
        protected void done() {
            textArea.append("Done\n");

            try {
                get();
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        }

        public void setLoopRunning(boolean running) {
            this.loopRunning = running;
        }

        public boolean isLoopRunning() {
            return loopRunning;
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }

    private static void createAndShowGui() {
        SwingWorkerExample mainPanel = new SwingWorkerExample();
        JFrame frame = new JFrame("SwingWorkerExample");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.add(mainPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }
}

【讨论】:

    【解决方案2】:

    您只附加最后发布的字符串(在给定的块中)

     @override
        protected void process(List<String> wordsToPrint)
        {
            String lastWordRecieved = wordsToPrint.get(wordsToPrint.size()-1);
            mainWindowTextArea.append(lastWord);  // not printing\appending all the words sent here by the publish calls
        }
    

    改成

         @override
            protected void process(List<String> wordsToPrint)
            {
                for(String part:wordsToPrint){
                 mainWindowTextArea.append(part);
                }
            }
    

    当您调用publish 时,这并不意味着会立即调用process。相反,已发布的项目会被堆叠,并在某个时间点作为项目列表传递。

    【讨论】:

    • 这个答案和之前的答案有什么不同?他提出了同样的建议,另外还提出了一个不错的建议,即确保调用了 get()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多