java - SwingWorker 中的取消异常

标签 java swing swingworker

我正在尝试通过单击 JFrame 表单上的按钮来取消某个功能。

这是我的工作函数:

private void start(final Callable<Void> func) {
        worker = new SwingWorker<Boolean, Integer>() {
            @Override
            protected Boolean doInBackground() throws Exception {
                publish(2);
                func.call();
                return true;
            }

            @Override
            protected void done() {
                boolean status;
                try {
                    status = get();
                    dialog.dispose();
                } catch (InterruptedException | ExecutionException e) {
                    progressBar.setString("ERROR");
                    Logger.getLogger(Parser.class.getName()).log(Level.SEVERE, null, e);
                }
            }

            @Override
            protected void process(List<Integer> chunks) {
                progressBar.setStringPainted(true);
                progressBar.setIndeterminate(true);

            }

        };

这就是我试图取消 SwingWorker 对象的方法:

   dialog.addWindowListener(new WindowAdapter() 
{

  @Override
  public void windowClosing(WindowEvent e)
  {

    worker.cancel(true);

  }
});

但是当我单击关闭按钮时,它给了我异常,并且在 doinBackground() 方法内没有取消 func 。如何停止 func 方法?

最佳答案

在一次关于Callable的可怜的误会之后和 CallableStatement接口(interface)(很抱歉,我必须暂时离开 JDBC :P)我所说的观点仍然有效(幸运的是)。您可以使用SwingWorker#isCancelled() done() 内的方法实现如下:

@Override
protected void done() {
    if(isCancelled()) {
        try {
            func.cancel(); // you need to provide this method
            dialog.dispose();
        } catch(InterruptedException ex) {
             progressBar.setString("ERROR");
             Logger.getLogger(Parser.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

当然,您需要为可调用实现提供一个 cancel() 方法,该方法可能很简单也可能很困难,具体取决于 call() 方法实际执行的操作。例如:

abstract class AbstractCancellableTask<T> implements Callable<T> {

    public abstract void cancel() throws InterruptedException;
}

示例

我已经使用 Callable 更新了之前的示例。请注意,当调用 worker.cancel(true) 方法时,任务将被取消。

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

public class Demo {

    private void createAndShowGUI() {

        final SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {

            private AbstractCancellableTask<Void> myCallable;

            @Override
            protected Void doInBackground() throws Exception {

                myCallable = new AbstractCancellableTask<Void>() {

                    private volatile boolean flag = true;

                    @Override
                    public void cancel() throws InterruptedException {
                        flag = false;
                    }

                    @Override
                    public Void call() throws Exception {
                        while(flag) {
                            System.out.println("Running heavy task...");

                        }
                        System.out.println("Stopped!");
                        return null;
                    }
                };

                myCallable.call();
                return null;
            }

            @Override
            protected void done() {
                if(isCancelled()) {
                    try {
                        myCallable.cancel();
                    } catch (InterruptedException ex) {
                        Logger.getLogger(Demo.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
        };

        JToggleButton button = new JToggleButton("Start...", false);
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JToggleButton toggleButton = (JToggleButton)e.getSource();
                if(toggleButton.isSelected()) {
                    worker.execute();
                    toggleButton.setText("Stop it!");
                } else {
                    worker.cancel(true);
                    toggleButton.setEnabled(false);
                }
            }
        });

        JPanel content = new JPanel();
        content.add(button);

        JFrame frame = new JFrame("Demo");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.getContentPane().add(content);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Demo().createAndShowGUI();
            }
        });
    }

    abstract class AbstractCancellableTask<T> implements Callable<T> {

        public abstract void cancel() throws InterruptedException;
    }
}

关于java - SwingWorker 中的取消异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22529451/

相关文章:

java - JPanel 不支持 setMinimumSize/ComponentListener

java - 找不到 Hadoop 作业类

java - system.nanoTime() 错误吗?

java - Swing组件占用大量内存

java - Java的SwingWorker和Android的AsyncTask的区别

java - 动态显示附加文本的 TextArea

java - 在执行另一个 SwingWorker 之前等待 SwingWorker 完成

java - [Azure] [Application Insights Java代理]无法创建InProcessTelemetryChannel,为空

java - 我如何用空行对 java JTable 进行排序并强制空行始终排在最后?

java - 我的 JFrame 闪烁