SwingWorker, done() 在 process() 调用完成之前执行
我已经与SwingWorker合作了一段时间,最终出现了一种奇怪的行为,至少对我来说是这样。我清楚地知道,由于性能原因,对publish()方法的几个调用在一个调用中合并。这对我来说是完全有道理的,我怀疑SwingWorker会保留某种队列来处理所有这些调用。
根据教程和API,当SwingWorker结束其执行时,要么doInBackground()正常完成,要么从外部取消工作线程,然后调用dound()方法。目前为止,一切都好。
但是我有一个例子(类似于教程中所示),其中在执行方法后会完成方法调用。由于这两种方法都在事件调度线程中执行,因此我希望在所有调用完成后执行。换句话说:process()
done()
done()
process()
预期:
Writing...
Writing...
Stopped!
结果:
Writing...
Stopped!
Writing...
示例代码
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
public class Demo {
private SwingWorker<Void, String> worker;
private JTextArea textArea;
private Action startAction, stopAction;
private void createAndShowGui() {
startAction = new AbstractAction("Start writing") {
@Override
public void actionPerformed(ActionEvent e) {
Demo.this.startWriting();
this.setEnabled(false);
stopAction.setEnabled(true);
}
};
stopAction = new AbstractAction("Stop writing") {
@Override
public void actionPerformed(ActionEvent e) {
Demo.this.stopWriting();
this.setEnabled(false);
startAction.setEnabled(true);
}
};
JPanel buttonsPanel = new JPanel();
buttonsPanel.add(new JButton(startAction));
buttonsPanel.add(new JButton(stopAction));
textArea = new JTextArea(30, 50);
JScrollPane scrollPane = new JScrollPane(textArea);
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(scrollPane);
frame.add(buttonsPanel, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private void startWriting() {
stopWriting();
worker = new SwingWorker<Void, String>() {
@Override
protected Void doInBackground() throws Exception {
while(!isCancelled()) {
publish("Writing...\n");
}
return null;
}
@Override
protected void process(List<String> chunks) {
String string = chunks.get(chunks.size() - 1);
textArea.append(string);
}
@Override
protected void done() {
textArea.append("Stopped!\n");
}
};
worker.execute();
}
private void stopWriting() {
if(worker != null && !worker.isCancelled()) {
worker.cancel(true);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Demo().createAndShowGui();
}
});
}
}