我有一个带有“开始”和“停止”按钮的窗口.开始按钮将启动算法,停止按钮应将其停止.我使用SwingWorker在后台运行算法,并且通常调用worker.cancel(true)应该停止算法运行.我也有一个标签,可以可视化状态,例如如果我按“停止”,则Labeltext更改为“已停止”,因此问题不在按钮的actionLister上.
我的代码如下所示:
public class MainWindow extends JFrame implements ActionListener, WindowListener
{
// Some code, like generating JFrame, JButtons and other stuff not affencting the task.
Worker worker = new Worker();
public void actionPerformed(ActionEvent e)
{
boolean isStarted = false;
// Start Button
if (e.getSource() == this.buttonStart)
{
if(!isStarted)
{
System.out.println("start");
labelSuccess.setText("Mapping started!");
this.setEnabled(true);
worker.execute();
isStarted = false;
}
}
// Stop Button
if (e.getSource() == this.buttonStop)
{
labelSuccess.setText("Mapping stopped!");
worker.cancel(true);
}
}
class Worker extends SwingWorker {
@Override
protected Void doInBackground() throws Exception {
if(!isCancelled())
{
mapp();
Thread.sleep(60);
if (isCancelled()) {
System.out.println("SwingWorker - isCancelled");
}
}
return null;
}
}
此时,按下“停止”按钮只会导致Label-Text更改,但是后台的算法仍在运行.现在,这困扰了我好一阵子,我实在受不了了.
非常感谢您的帮助,不胜感激.
edit1:我现在在actionPerformed之外生成了一个新的worker实例,因此现在每次单击鼠标都不会生成新的Worker.
解决方法:
也许如果在Worker类的doInBackground()方法上使用while而不是if,则可以解决您的问题.您必须退出whilep循环,因为您只想一次调用它.您应该执行以下操作:
class Worker extends SwingWorker {
@Override
protected Void doInBackground() throws Exception {
mapp();
while(!isCancelled()){
Thread.sleep(60);
}
System.out.println("SwingWorker - isCancelled");
return null;
}
这个link可能有助于理解如何使用SwingWorker.
编辑:
如您在另一个问题(如this或this)上看到的那样,使用SwingWorker在管理cancel方法方面存在一些问题,因为该方法试图取消执行此任务.如果任务已经完成,已经被取消或由于某些其他原因而无法取消,则该尝试将失败,例如Oracle的解释,这些“其他原因”将在我发布的链接中进行讨论.
您可以直接使用线程来解决您的问题.您的代码将如下所示:
public class MainWindow extends JFrame implements ActionListener, WindowListener
{
// Some code, like generating JFrame, JButtons and other stuff not affencting the task.
final Thread th1 = new Thread(new Runnable() {
@Override
public void run() {
mapp();
}
});
public void actionPerformed(ActionEvent e)
{
boolean isStarted = false;
// Start Button
if (e.getSource() == this.buttonStart)
{
if(!isStarted)
{
System.out.println("start");
labelSuccess.setText("Mapping started!");
this.setEnabled(true);
th1.start();
isStarted = false;
}
}
// Stop Button
if (e.getSource() == this.buttonStop)
{
labelSuccess.setText("Mapping stopped!");
th1.stop();
}
}
该解决方案使用了不建议使用的stop()方法,但是它可以工作.我已经尝试过使用interrupt(),但是我不知道为什么线程要运行到完成mapp()的执行.显然,使用stop()并不是最好的方法,但可以在完成mapp()之前停止执行.
我建议您了解有关SwingWorker,线程和任务的更多信息,以找到解决问题的最佳方法.
标签:swingworker,multithreading,swing,java
来源: https://codeday.me/bug/20191122/2058049.html