所以我进入SwingWorkers来处理我使用不同的Classes和Threads操作文本。如下所示,我的Swingworker获取文件路径并扫描文本,将行传递给String。使用getData()
我将扫描的String返回到我的主类。但是,在我的Worker类的构造函数中运行方法scanFile()
之前,这不起作用。 所以我的问题是:为什么我的SwingWorker类没有正确运行doInBackground()
?
public class ScanWorker extends SwingWorker<Void, Void> {
private File file;
private String text;
ScanWorker(File file) {
this.file = file;
}
@Override
protected Void doInBackground() throws Exception {
scanFile();
return null;
}
public String getData() {
return text;
}
private void scanFile() {
String line = "";
try {
Scanner scan = new Scanner(file);
while(scan.hasNextLine()) {
line = scan.nextLine();
if(!scan.hasNextLine()) {
text += line;
} else {
text += line + "\n";
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
答案 0 :(得分:1)
您不应该为返回值添加自己的getData()
方法,因为这不是线程安全的。正是SwingWorker试图通过提供自己的机制将结果传回Swing线程来避免的。结果类型是SwingWorker的第一个类型参数,因此您应该SwingWorker<Void,Void>
而不是SwingWorker<String,Void>
。
将protected Void doInBackground()
更改为protected String doInBackground()
(因为这是您的结果类型)。
删除text
字段,然后从doInBackground()
返回结果字符串。
从工作线程返回doInBackground()
方法的结果后,将在Swing线程上调用done()
方法。你错过了这种方法。从该方法,您可以调用get()
来检索结果。添加方法如下:
@Override
protected void done() {
String result;
try {
result = get();
} catch (Exception e) {
throw new RuntimeException(e);
}
// Now do whatever you want with the loaded data:
...
}
在您通过调用execute()
方法启动之前,SwingWorker不会执行任何操作。确保你这样做!
P.S。您不应该直接在String变量中构建文本,因为每次向其追加一行时都会重新遍历整个字符串,这会产生恶劣的性能。使用StringBuilder
进行此类操作,仅在最后调用toString()
。
或者,如果您只想将文件重新连接在一起,那么没有必要将文件拆分为行,您可以一次性读取整个文件:
@Override
protected String doInBackground() throws Exception {
return new String(
java.nio.file.Files.readAllBytes(file.toPath()),
java.nio.charset.StandardCharsets.UTF_8);
}
答案 1 :(得分:0)
如果你将scanFile()
放在构造函数中,那么你在当前线程上执行了该方法,从而违背了SwingWorker
的目的。
基于 pull 的方法,来自工作人员的getData()
,可能是在你execute
后立即出错的:你必须覆盖done()
和做与生产结果有关的任何工作。或者,您可以使用publish
和process
方法,在工作线程生成EDT时,您将收到EDT中的数据。