SwingWorker not responding

余生颓废 提交于 2019-11-26 23:17:17

if I add Thread.sleep(...), it does work, though, it throws a InterruptedException

The code that apparently produces the exception (copied from OP's edit):

while (!isCancelled()) {
    counter %= arrNames.length;
    // System.out.format("Counter : %d%n", counter);
    publish(arrNames[counter]);
    try {
        Thread.sleep(30); // throws
    } catch (InterruptedException ie) {
        ie.printStackTrace();
    }
    counter++;
}

The reason, though, is the code that cancels the worker (in the actionListener):

backgroundTask.cancel(true);

which explicitly tells the worker to cancel by .. interrupting the thread. From its api doc:

mayInterruptIfRunning - true if the thread executing this task should be interrupted; otherwise, in-progress tasks are allowed to complete

As an aside: catching the exception and doing nothing (thereby effectively ignoring the interrupt) is not the best of ideas. Probably not too damaging in this case - due to checking the cancelled status. Typical worker implementations either catch and return, after doing some internal cleanup if needed, or don't handle it at all.

trashgod

Amplifying on the other answers, don't update the GUI from your background thread, which blocks the EDT, and don't try to avoid the problem with invokeLater(). Instead, publish() the desired result and update both statusLabel and tArea in process(), as suggested below. For testing, Thread.sleep(100) simulates a small latency, but you can use Thread.yield(), as shown here. You can also update the GUI in a PropertyChangeListener, as shown here.

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.*;
import javax.swing.*;

public class SwingWorkerExample1 {

    private JLabel statusLabel;
    private JTextArea tArea;
    private JButton startButton;
    private JButton stopButton;
    private BackgroundTask backgroundTask;
    private ActionListener buttonActions = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent ae) {
            JButton source = (JButton) ae.getSource();
            if (source == startButton) {
                startButton.setEnabled(false);
                stopButton.setEnabled(true);
                backgroundTask = new BackgroundTask();
                backgroundTask.execute();
            } else if (source == stopButton) {
                backgroundTask.cancel(true);
                stopButton.setEnabled(false);
                startButton.setEnabled(true);
            }
        }
    };

    private void displayGUI() {
        JFrame frame = new JFrame("Swing Worker Example");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        JPanel contentPane = new JPanel();
        contentPane.setBorder(
            BorderFactory.createEmptyBorder(5, 5, 5, 5));
        contentPane.setLayout(new BorderLayout(5, 5));

        statusLabel = new JLabel("Status Bar", JLabel.CENTER);

        tArea = new JTextArea(20, 20);
        tArea.setWrapStyleWord(true);
        tArea.setLineWrap(true);
        JScrollPane textScroller = new JScrollPane();
        textScroller.setBorder(
            BorderFactory.createTitledBorder("Textual OUTPUT : "));
        textScroller.setViewportView(tArea);

        startButton = new JButton("Start");
        startButton.addActionListener(buttonActions);
        stopButton = new JButton("Stop");
        stopButton.setEnabled(false);
        stopButton.addActionListener(buttonActions);
        JPanel buttonPanel = new JPanel();
        buttonPanel.add(startButton);
        buttonPanel.add(stopButton);

        contentPane.add(statusLabel, BorderLayout.PAGE_START);
        contentPane.add(textScroller, BorderLayout.CENTER);
        contentPane.add(buttonPanel, BorderLayout.PAGE_END);

        frame.setContentPane(contentPane);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    private class BackgroundTask extends SwingWorker<Void, String> {

        private int counter = 0;
        private String[] arrNames = {"US Rates Strategy Cash",
            "Pavan Wadhwa(1-212) 844-4597", "Srini Ramaswamy(1-212) 844-4983",
            "Meera Chandan(1-212) 855-4555", "Kimberly Harano(1-212) 823-4996",
            "Feng Deng(1-212) 855-2555", "US Rates Strategy Derivatives",
            "Srini Ramaswamy(1-212) 811-4999",
            "Alberto Iglesias(1-212) 898-5442",
            "Praveen Korapaty(1-212) 812-3444", "Feng Deng(1-212) 812-2456",
            "US Rates Strategy Derivatives", "Srini Ramaswamy(1-212) 822-4999",
            "Alberto Iglesias(1-212) 822-5098",
            "Praveen Korapaty(1-212) 812-3655", "Feng Deng(1-212) 899-2222"};

        public BackgroundTask() {
            statusLabel.setText((this.getState()).toString());
        }

        @Override
        protected Void doInBackground() {
            while (!isCancelled()) {
                counter %= arrNames.length;
                publish(arrNames[counter]);
                counter++;
                try {
                    Thread.sleep(100); // simulate latency
                } catch (InterruptedException ex) {
                    publish("Cancelled: " + isCancelled());
                }
            }
            return null;
        }

        @Override
        protected void process(java.util.List<String> messages) {
            statusLabel.setText((this.getState()).toString());
            for (String message : messages) {
                tArea.append(String.format(message + "%n"));
            }
        }
    }

    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                new SwingWorkerExample1().displayGUI();
            }
        };
        EventQueue.invokeLater(runnable);
    }
}

comments

  • @kleopatra that's a documentation bug, fixed in jdk7 at least :-), please which of JDKs those bugs are shown as from carousel ....,

  • wait/notify is for thread, SwingWorker is Future, very bad implemented, means without notifiers, you put something to the tube and waiting on another side,

  • seems like as nothing betweens one and second side of this tube, this reason why I tried to invoke Thread, Runnable, Executor(Runnable) from doInBackground, and to ignore publish, process, setProcess

  • another funny issue is to get() and exception(s) all exception, not only 1st. from one and second side of this tube

  • there are two ways how to use SwingWokrer

    1. try to avoid to use SwingWorker

    2. use doInBackground as bridge for workers thread, for output to use publish, process, setProcess, wait for done(), and use done() as notifier for get an exception, notifier that SwingWorker ended

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!