Java SwingWorker中的取消异常
我正试图通过点击JFrame表单上的按钮来取消一个函数 以下是我的工作函数:Java SwingWorker中的取消异常,java,swing,swingworker,Java,Swing,Swingworker,我正试图通过点击JFrame表单上的按钮来取消一个函数 以下是我的工作函数: private void start(final Callable<Void> func) { worker = new SwingWorker<Boolean, Integer>() { @Override protected Boolean doInBackground() throws Exception {
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);
}
};
但当我单击close按钮时,它会给出异常,并且
func
在doinBackground()方法中不会被取消。如何停止func
方法?在对和接口产生了令人遗憾的误解(很抱歉,我不得不离开JDBC一段时间:p)之后,我提出的观点仍然有效(幸运的是)。您可以在实现中使用如下方法:
@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;
}
func如何知道它正在被取消?作为一般规则,doInBackground必须合作(即注意被取消并停止它正在做的任何事情)-但不知道如何在这里应用该规则;-)嗯,这是否意味着不可能取消doInBackground操作?不,但你必须这么做…哦,我犯了一个可怕的错误:(你没有使用接口…对数据库做了太多工作我到处都看到JDBC…很抱歉!但主要概念仍然有效,你可以使用SwingWorker#isCancelled()
并为您的func
提供一些cancel
方法。虽然这并不容易…@AloneInTheDarkNo,关键是提供一个cancel()
method。这只是一个实现示例。在这种情况下,繁重的任务是循环打印字符串,直到flag
为false。只有当一些外部对象调用cancel()时才会发生这种情况
方法将标志设置为false,这只有在SwingWorker被取消时才会发生。我说清楚了吗?如果没有,请告诉我。@aloneinthedark您有在函数中执行的代码吗?如果有,那么您可以创建一个新的AbstractCancelableTask
并将该代码放入调用()中
方法实现。然后您必须管理如何取消该代码的执行(如果可能)。如果您没有该代码,并且只从外部接收到一个可调用函数,那么我担心您将无法实现您的目标。@aloneinthedark不客气!正如我所说,根据需要执行的操作,这可能很容易,也可能很难。希望这是第一个选项;) @AloneInTheDark@AloneInTheDark某些gui对象访问doInBackground中的视图,因此您的函数不能!
abstract class AbstractCancellableTask<T> implements Callable<T> {
public abstract void cancel() throws InterruptedException;
}
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;
}
}