Java SwingWorker IsInterputed在取消后返回false
我有一段代码可以下载一个文件。这发生在SwingWorker doInBackground方法中。(参见下面的代码)文件是一个文件对象(temp dir)。连接是一个URLConnection对象,它保存要下载的文件的url。(url.openConnection()) 下载在SwingWorker中正常工作,除了取消Java SwingWorker IsInterputed在取消后返回false,java,multithreading,swingworker,Java,Multithreading,Swingworker,我有一段代码可以下载一个文件。这发生在SwingWorker doInBackground方法中。(参见下面的代码)文件是一个文件对象(temp dir)。连接是一个URLConnection对象,它保存要下载的文件的url。(url.openConnection()) 下载在SwingWorker中正常工作,除了取消 SwingWorker<Integer,Integer> swingWorker = new SwingWorker<Integer,Integer>()
SwingWorker<Integer,Integer> swingWorker = new SwingWorker<Integer,Integer>() {
int contentLength = 0;
int bytesDownloaded = 0;
double speed = 0;
@Override
protected Integer doInBackground() throws Exception {
setStatus("Dowloading...");
URL url = null;
URLConnection connection = null;
try {
url = new URL(MainScreen.getUrl()); // Gets a URL entered earlier to dowload
connection = url.openConnection();
} catch (Exception ex) {
ex.printStackTrace(System.err);
}
BufferedOutputStream outputStream = null;
try {
BufferedInputStream inputStream = new BufferedInputStream(connection.getInputStream());
outputStream = new BufferedOutputStream(new FileOutputStream(doelBestand));
contentLength = connection.getContentLength();
long start = System.nanoTime();
final double nanosPerSecond = 1000000000.0;
final double bytesPerMB = 1024 * 1024;
while(true) {
int b = inputStream.read();
bytesDownloaded += b;
speed = nanosPerSecond / bytesPerMB * bytesDownloaded / (System.nanoTime() - start + 1);
process();
if (b == -1 || Thread.interrupted()) {
break;
}
outputStream.write(b);
}
} catch (IOException ex) {
ex.printStackTrace(System.err);
} finally {
try {
if(outputStream != null) {
outputStream.close();
}
} catch (IOException ex) { }
try {
if(connection != null) {
connection.getInputStream().close();
}
} catch (IOException ex) { }
}
return 100;
}
@Override
protected void done() {
progressBar.setIndeterminate(false);
progressBar.setValue(100);
lblPercent.setText("100 %");
btnStartCancel.setEnabled(false);
btnOpenFolder.setEnabled(true);
chkCloseOnFinish.setEnabled(false);
state = State.DONE;
}
protected void process() {
DecimalFormat df = new DecimalFormat("0.##");
if(speed > 0) {
lblDownloadSpeed.setText(df.format(speed) + " mb/s");
}
if(contentLength > 0) {
Integer percent = (int) (bytesDownloaded / (contentLength / 100.0));
progressBar.setValue(percent);
lblPercent.setText(percent + " %");
} else {
progressBar.setIndeterminate(true);
}
}
};
但是isInterrupted()
总是返回false,因此它继续运行线程,但是cancel函数确实返回true
我在(!isCancelled())时也尝试了,但也不断返回false
还有一个问题是,当它被取消时,它永远不会停止,因此它成为一个无限线程。(int b在添加时继续运行,bytesDownloaded将不断增长)。它不是无限的,只要下载完成而没有取消(那么b将是-1),循环就会中断
如何确保swingWorker将中止下载?我猜阻塞方法是来自InputStream类的read(),或者其他方法正在阻塞一个。因此,Despides,您需要编写一个结构良好的方法,但其中一个操作会阻塞执行流程。因此,除了插入线程(这是终止线程所必需的)之外,您还必须中断阻塞操作(我猜是读取输入流),首先,确保您调用的SwingWorker
实例与启动后台任务时使用的实例相同。由于您没有在显示给我们的SwingWorker
语句中创建您的SwingWorker
,因此很可能您在错误的位置创建了它(并覆盖了引用变量)。此外,当您从后台线程访问甚至操作GUI时,您的实现从根本上被破坏了。感谢您的回复@霍尔格switch语句紧跟在swingworker之后。两者的功能也相同。如您所见,它在就绪状态下成功执行swingWorker.execute()
没有其他线程,这意味着我们可以排除它可能被覆盖的可能性。从worker更新GUI的更合适的方法是什么?您在开关
语句之前创建swingworker,也就是说,即使状态
正在下载
,您也在创建swingworker?想想看。正确的更新方式是。您可以使用属性更改侦听器
通知或发布
/进程
队列。为什么不尝试使用自定义标志?说布尔值(而不是使用SwingWorker的信号基础系统)。我怀疑cancel方法只设置了一个内部布尔值,这与isCanceled()上返回的值相同。
switch(state) {
case READY:
state = State.DOWNLOADING;
btnStartCancel.setText("Cancel");
swingWorker.execute();
break;
case DOWNLOADING:
swingWorker.cancel(true);
progressBar.setIndeterminate(false);
lblPercent.setText("Download was cancelled by the user.");
btnStartCancel.setText("Start");
btnStartCancel.setEnabled(true);
break;
case DONE:
// Do nothing
break;
}