如何取消SwingWorker的执行?

目前我有两个SwingWorker线程在后台工作。 如果发生exception,该方法停止工作,但线程仍然运行。

如果发生exception,我该如何停止执行并杀死doInBackground()的线程?

this.cancel(true)不会销毁/closures线程。 我怎样才能做到这一点?

 @Override protected Boolean doInBackground() throws Exception { try { while (true) { //some code here return true; } } catch (Exception e) { this.cancel(true); //<-- this not cancel the thread return false; } } 

我在NetBeans的debugging中看到这些线程。

 'AWT-EventQueue-0' em execução 'AWT-Windows' em execução 'SwingWorker-pool-1-thread-1' em execução 'SwingWorker-pool-1-thread-2' em execução //*em execução = in execution 

默认情况下, SwingWorker重用了工作线程,所以尽pipedoInBackground()已经返回了,但仍然可以看到执行你的方法的线程。

您可以通过查看NetBeans报告的线程名称来识别此事实: SwingWorker-pool-1-thread-1 ,其中该SwingWorkerpipe理。

如果你想要更多的控制,你也可以将SwingWorker实例传递给Executor

只需检查SwingWorker和执行器 javadoc的进一步信息。

此外,不应该从doInBackground()调用SwingWorker.cancel() ,而应该从另一个线程(通常为EDT doInBackground()调用SwingWorker.cancel() ,例如当用户在进度对话框中单击“ 取消”button时。

作为jzd montions,有方法取消(布尔mayInterruptIfRunning) ; 为exapmle

编辑:与取消(真); 你必须(总是)抛出一个java.util.concurrent.CancellationExceptionexception

 import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.ArrayList; public class SwingWorkerExample extends JFrame implements ActionListener { private static final long serialVersionUID = 1L; private final JButton startButton, stopButton; private JScrollPane scrollPane = new JScrollPane(); private JList listBox = null; private DefaultListModel listModel = new DefaultListModel(); private final JProgressBar progressBar; private mySwingWorker swingWorker; public SwingWorkerExample() { super("SwingWorkerExample"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); getContentPane().setLayout(new GridLayout(2, 2)); startButton = makeButton("Start"); stopButton = makeButton("Stop"); stopButton.setEnabled(false); progressBar = makeProgressBar(0, 99); listBox = new JList(listModel); scrollPane.setViewportView(listBox); getContentPane().add(scrollPane); //Display the window. pack(); setVisible(true); } //Class SwingWorker<T,V> T - the result type returned by this SwingWorker's doInBackground //and get methods V - the type used for carrying out intermediate results by this SwingWorker's //publish and process methods private class mySwingWorker extends javax.swing.SwingWorker<ArrayList<Integer>, Integer> { //The first template argument, in this case, ArrayList<Integer>, is what s returned by doInBackground(), //and by get(). The second template argument, in this case, Integer, is what is published with the //publish method. It is also the data type which is stored by the java.util.List that is the parameter //for the process method, which recieves the information published by the publish method. @Override protected ArrayList<Integer> doInBackground() { //Returns items of the type given as the first template argument to the SwingWorker class. if (javax.swing.SwingUtilities.isEventDispatchThread()) { System.out.println("javax.swing.SwingUtilities.isEventDispatchThread() returned true."); } Integer tmpValue = new Integer(1); ArrayList<Integer> list = new ArrayList<Integer>(); for (int i = 0; i < 100; i++) { for (int j = 0; j < 100; j++) { //find every 100th prime, just to make it slower tmpValue = FindNextPrime(tmpValue.intValue()); //isCancelled() returns true if the cancel() method is invoked on this class. That is the proper way //to stop this thread. See the actionPerformed method. if (isCancelled()) { System.out.println("SwingWorker - isCancelled"); return list; } } //Successive calls to publish are coalesced into a java.util.List, which is what is received by process, //which in this case, isused to update the JProgressBar. Thus, the values passed to publish range from //1 to 100. publish(new Integer(i)); list.add(tmpValue); } return list; }//Note, always use java.util.List here, or it will use the wrong list. @Override protected void process(java.util.List<Integer> progressList) { //This method is processing a java.util.List of items given as successive arguments to the publish method. //Note that these calls are coalesced into a java.util.List. This list holds items of the type given as the //second template parameter type to SwingWorker. Note that the get method below has nothing to do with the //SwingWorker get method; it is the List's get method. This would be a good place to update a progress bar. if (!javax.swing.SwingUtilities.isEventDispatchThread()) { System.out.println("javax.swing.SwingUtilities.isEventDispatchThread() + returned false."); } Integer percentComplete = progressList.get(progressList.size() - 1); progressBar.setValue(percentComplete.intValue()); } @Override protected void done() { System.out.println("doInBackground is complete"); if (!javax.swing.SwingUtilities.isEventDispatchThread()) { System.out.println("javax.swing.SwingUtilities.isEventDispatchThread() + returned false."); } try { //Here, the SwingWorker's get method returns an item of the same type as specified as the first type parameter //given to the SwingWorker class. ArrayList<Integer> results = get(); for (Integer i : results) { listModel.addElement(i.toString()); } } catch (Exception e) { System.out.println("Caught an exception: " + e); } startButton(); } boolean IsPrime(int num) { //Checks whether a number is prime int i; for (i = 2; i <= num / 2; i++) { if (num % i == 0) { return false; } } return true; } protected Integer FindNextPrime(int num) { //Returns next prime number from passed arg. do { if (num % 2 == 0) { num++; } else { num += 2; } } while (!IsPrime(num)); return new Integer(num); } } private JButton makeButton(String caption) { JButton b = new JButton(caption); b.setActionCommand(caption); b.addActionListener(this); getContentPane().add(b); return b; } private JProgressBar makeProgressBar(int min, int max) { JProgressBar progressBar1 = new JProgressBar(); progressBar1.setMinimum(min); progressBar1.setMaximum(max); progressBar1.setStringPainted(true); progressBar1.setBorderPainted(true); getContentPane().add(progressBar1); return progressBar1; } private void startButton() { startButton.setEnabled(true); stopButton.setEnabled(false); System.out.println("SwingWorker - Done"); } @Override public void actionPerformed(ActionEvent e) { if ("Start" == null ? e.getActionCommand() == null : "Start".equals(e.getActionCommand())) { startButton.setEnabled(false); stopButton.setEnabled(true); // Note that it creates a new instance of the SwingWorker-derived class. Never reuse an old one. (swingWorker = new mySwingWorker()).execute(); // new instance } else if ("Stop" == null ? e.getActionCommand() == null : "Stop".equals(e.getActionCommand())) { startButton.setEnabled(true); stopButton.setEnabled(false); swingWorker.cancel(true); // causes isCancelled to return true in doInBackground swingWorker = null; } } public static void main(String[] args) { // Notice that it kicks it off on the event-dispatching thread, not the main thread. SwingUtilities.invokeLater(new Runnable() { @Override public void run() { SwingWorkerExample swingWorkerExample = new SwingWorkerExample(); } }); } } 

有一个cancel()方法。 你的代码将不得不注意这一点。 如果它在exception之后继续运行,那么看起来你的代码是忽略了它不应该的exception。

任何经过的人:当一个SwingWorker被取消时,done()在doInBackground()返回之前被调用。

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6826514

杰夫

您需要经常在doInBackground()代码中添加Thread.sleep(1)调用。 在你的睡眠catch块,添加return 。 我有同样的问题,这就像一个魅力。

来源: https : //blogs.oracle.com/swinger/entry/swingworker_stop_that_train

直到SwingWoker它修复http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6826514这里一个简单的(testing)版本与基本(类似)function,然后SwingWoker

 /* * To change this template, choose Tools | Templates * and open the template in the editor. */ package tools; import java.util.LinkedList; import java.util.List; import javax.swing.SwingUtilities; /** * * @author patrick */ public abstract class MySwingWorker<R,P> { protected abstract R doInBackground() throws Exception; protected abstract void done(R rvalue, Exception ex, boolean canceled); protected void process(List<P> chunks){} protected void progress(int progress){} private boolean cancelled=false; private boolean done=false; private boolean started=false; final private Object syncprogress=new Object(); boolean progressstate=false; private int progress=0; final private Object syncprocess=new Object(); boolean processstate=false; private LinkedList<P> chunkes= new LinkedList<>(); private Thread t= new Thread(new Runnable() { @Override public void run() { Exception exception=null; R rvalue=null; try { rvalue=doInBackground(); } catch (Exception ex) { exception=ex; } //Done: synchronized(MySwingWorker.this) { done=true; final Exception cexception=exception; final R crvalue=rvalue; final boolean ccancelled=cancelled; SwingUtilities.invokeLater(new Runnable() { @Override public void run() { done(crvalue, cexception, ccancelled); } }); } } }); protected final void publish(P p) { if(!Thread.currentThread().equals(t)) throw new UnsupportedOperationException("Must be called from worker Thread!"); synchronized(syncprocess) { chunkes.add(p); if(!processstate) { processstate=true; SwingUtilities.invokeLater(new Runnable() { @Override public void run() { List<P> list; synchronized(syncprocess) { MySwingWorker.this.processstate=false; list=MySwingWorker.this.chunkes; MySwingWorker.this.chunkes= new LinkedList<>(); } process(list); } }); } } } protected final void setProgress(int progress) { if(!Thread.currentThread().equals(t)) throw new UnsupportedOperationException("Must be called from worker Thread!"); synchronized(syncprogress) { this.progress=progress; if(!progressstate) { progressstate=true; SwingUtilities.invokeLater(new Runnable() { @Override public void run() { int value; //Acess Value synchronized(syncprogress) { MySwingWorker.this.progressstate=false; value=MySwingWorker.this.progress; } progress(value); } }); } } } public final synchronized void execute() { if(!started) { started=true; t.start(); } } public final synchronized boolean isRunning() { return started && !done; } public final synchronized boolean isDone() { return done; } public final synchronized boolean isCancelled() { return cancelled; } public final synchronized void cancel() { if(started && !cancelled && !done) { cancelled=true; if(!Thread.currentThread().equals(t)) t.interrupt(); } } }