gpt4 book ai didi

java - 使用 isCancelled() 时 SwingWorker 不会停止

转载 作者:行者123 更新时间:2023-12-01 12:38:31 24 4
gpt4 key购买 nike

我创建了一个有 3 个按钮的 GUI;连接、断开、中止。它们都共享一个公共(public) SwingWorker 线程,但由于某种原因,除非我按下中止按钮,否则该线程永远不会完成。

我还没有为断开连接按钮编写任何代码,但即便如此,它与我的问题无关。但是,为什么线程不直接完成并打印 Done陈述?我的猜测是它陷入了 this.isCancelled()循环,但即使我这样做:

while(!this.isCancelled() || !this.isDone()) { // run loop }

它从不打印Done

只有在我按下中止按钮后,线程才会完成。我正在使用isCancelled()循环方法,因为这似乎是取消 SwingWorker 的推荐方法。

我只发布下面的相关代码,因为实际上有数百行。

   private class ButtonListener implements ActionListener {

private MyWorker worker;

@Override
public void actionPerformed(ActionEvent e) {

if(e.getSource().equals(connectButton)) {

worker = new MyWorker(activityTextArea);
worker.execute();
activityTextArea.append("Connect Button Pressed");
}

if(e.getSource().equals(disconnectButton)) {

activityTextArea.append("Disconnect Button Pressed");
}

if(e.getSource().equals(abortButton)) {

worker.cancel(true);
activityTextArea.append("Abort Button Pressed");
}
}
}

这是 SwingWorker:

public class MyWorker extends SwingWorker<Void, Void> {

private JTextArea textArea;

MyWorker(JTextArea textArea) {
this.textArea = textArea;
}

private void startWorker() {

ProcessBuilder pb = new ProcessBuilder();
pb.command("aCmd");

Process p;

try {
p = pb.start();

BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));

String line;

while((line = br.readLine()) != null) {
textArea.append(line + "\n");
}
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

@Override
protected Void doInBackground() throws Exception {
// TODO Auto-generated method stub
boolean isFirstTime = true;

while(!this.isCancelled()) {

if(this.isDone()) { break; }

Thread.sleep(3000);

if(isFirstTime) {
startWorker();
isFirstTime = false;
}
}

return null;
}

@Override
protected void done() {
textArea.append("Done\n");
}
}

最佳答案

这里的问题在于 MyWorker.doInBackground() 方法的实现, isDone() 用于控制循环的执行。这可能不是您希望 doInBackground() 工作的方式。

要真正了解发生了什么,我们需要考虑 isDone() 的行为和 SwingWorker 的生命周期。

isDone() 方法在以下情况下返回 true:

  • done() 执行完成后
  • 该工作人员已被取消
  • 由于某些异常而异常终止。

SwingWorker 生命周期

  • PENDING:从对象构造到调用 doInBackground 之前期间的状态。
  • STARTED:从调用 doInBackground() 之前不久到调用 done() 之前不久期间的状态。 SwingWorker 在进入此状态之前会被分配一个工作线程,并且该工作线程执行 doInBackground()。
    • 在此状态下执行 doInBackground() 时,worker 可以使用 publish(..) 发送中间结果,然后获取 process(.. ) 由事件调度线程 (EDT) 实现。
  • DONE:在事件调度线程 (EDT) 中的 done() 完成执行后,会转换到此状态。这是对象剩余存在的最终状态。

为了编写高性能且无故障的 GUI,了解上述工作流程非常重要。

根据上述讨论,您可能希望替换 if(this.isDone()) { break; } 包含反射(reflect)您预期处理完成情况的内容。

这里的另一个问题是,您正在由 doInBackground() 调用的方法中执行与 swing 相关的 Activity 。 textArea.append(line + "\n"); 应该发生在事件调度线程中执行的 process(..) 方法中,如下所示:

public class MyWorker extends SwingWorker<Void, String> {

@Override
protected void process(List<String> chunks) {
for (String line : chunks) {
textArea.append(line + "\n"); // display intermediate results from publish()
}
}

private void startWorker() throws IOException {

ProcessBuilder pb = new ProcessBuilder("aCmd");
BufferedReader br = null;

try {
Process p = pb.start();
br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
publish(line); // publish a chunk of result to process(..)
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) br.close();
}
}

引用:http://docs.oracle.com/javase/7/docs/api/javax/swing/SwingWorker.html

关于java - 使用 isCancelled() 时 SwingWorker 不会停止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25345105/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com