Java SwingWorker上的异常不可捕获
我一直在使用Java线程,以便为在管道中运行进程提供GUI平台。我已经设法解决了SwingWorker的许多问题,但这个问题似乎令人费解 我的Java SwingWorker上的异常不可捕获,java,multithreading,swing,exception-handling,swingworker,Java,Multithreading,Swing,Exception Handling,Swingworker,我一直在使用Java线程,以便为在管道中运行进程提供GUI平台。我已经设法解决了SwingWorker的许多问题,但这个问题似乎令人费解 我的SwingWorker看起来像: SwingWorker<Boolean,Object> worker = new SwingWorker<Boolean,Object>() { @Override public Boolean doInBackground() { re
SwingWorker
看起来像:
SwingWorker<Boolean,Object> worker = new SwingWorker<Boolean,Object>() {
@Override
public Boolean doInBackground() {
return launchBlockingPipelineProcess(process, instance, project, logger, state);
}
@Override
protected void done(){
boolean success = false;
try{
success = get();
if (!success){
state.setTaskFailed(true);
}
if (process.getStatus().equals(Status.Interrupted)){
state.setTaskInterrupted(true);
}
}catch (Exception ex){
state.setTaskFailed(true);
}
processCompleted(process, success, state);
}
};
EDIT2:在Eclipse中调试时,我可以在抛出它的行上的断点处停止(好的,一步之前);该点的堆栈跟踪为:
Nifti1Dataset.readVolBlob(short) line: 2179
Nifti1Dataset.readDoubleVol(short) line: 1916
NiftiVolumeLoader.setGrid3DBlocking(Grid3D, int, ProgressUpdater) line: 186
NiftiVolumeLoader(VolumeFileLoader).setGrid3D(Grid3D, int, ProgressUpdater) line: 237
NiftiVolumeLoader(VolumeFileLoader).getGrid3D(VolumeInputOptions, int, ProgressUpdater) line: 139
NiftiVolumeLoader(VolumeFileLoader).getGrid3D(int) line: 97
MincFunctions.create_volume_atlas_masks() line: 5278
MincFunctions.run_command(String) line: 153
MincFunctions(CommandInstance).execute(String[]) line: 87
JavaProcess.run(String[], long) line: 141
PipelineFunctions.launchBlockingPipelineProcess(PipelineProcessInstance, String, InterfaceProject, String, PipelineState) line: 238
PipelineFunctions.launchPipelineProcess(PipelineProcessInstance, String, InterfaceProject, String, boolean, PipelineState) line: 78
PipelineFunctions.launchPipelineProcess(PipelineProcessInstance, boolean, PipelineState) line: 52
PipelineProcessInstance.launch(boolean) line: 187
InterfacePipeline.launch(boolean) line: 388
PipelineLauncher.doInBackground() line: 57
PipelineLauncher.doInBackground() line: 1
SwingWorker$1.call() line: 277
FutureTask$Sync.innerRun() line: 303
SwingWorker$2(FutureTask<V>).run() line: 138
PipelineLauncher(SwingWorker<T,V>).run() line: 316
ThreadPoolExecutor$Worker.runTask(Runnable) line: 886
ThreadPoolExecutor$Worker.run() line: 908
Thread.run() line: 662
Nifti1Dataset.readVolBlob(短)行:2179
Nifti1Dataset.readDoubleVol(短)行:1916
setGrid3DBlocking(Grid3D,int,ProgressUpdater)行:186
NiftivolumLoader(VolumeFileLoader).setGrid3D(Grid3D,int,ProgressUpdater)行:237
NiftiVolumeLoader(VolumeFileLoader).getGrid3D(VolumeInputOptions,int,ProgressUpdater)行:139
NiftivolumLoader(VolumeFileLoader).getGrid3D(int)行:97
MincFunctions.create\u volume\u atlas\u masks()行:5278
MincFunctions.run_命令(字符串)行:153
MincFunctions(CommandInstance).execute(字符串[])行:87
运行(字符串[],长)行:141
PipelineFunctions.launchBlockingPipelineProcess(PipelineProcessInstance,String,InterfaceProject,String,PipelineState)行:238
PipelineFunctions.launchPipelineProcess(PipelineProcessInstance,String,InterfaceProject,String,boolean,PipelineState)行:78
PipelineFunctions.launchPipelineProcess(PipelineProcessInstance,boolean,PipelineState)行:52
PipelineProcessInstance.launch(布尔)行:187
InterfacePiline.launch(布尔)行:388
PipelineLauncher.doInBackground()行:57
PipelineLauncher.doInBackground()行:1
SwingWorker$1.call()行:277
FutureTask$Sync.innerRun()行:303
SwingWorker$2(FutureTask).run()行:138
PipelineLauncher(SwingWorker).run()行:316
ThreadPoolExecutor$Worker.runTask(Runnable)行:886
ThreadPoolExecutor$Worker.run()行:908
Thread.run()行:662
是可以从SwingWorker
的方法done()
中获取异常
,但需要严格命名每个线程,尤其是,我还没有找到另一种方法来解决这个问题的可能性我解决了一个类似的表问题,在AWT线程绘制UI时不进行干扰。
我使用invokeLater()
将我的线程与UI线程同步
更多详情请参见。@Adrian,谢谢你的建议;我不认为我直接从
SwingWorker
线程进行任何UI更新;我确实会对JTree
节点进行更新,以指示流程的成功或失败,但我使用发布/流程机制来实现这一点,这应该确保所有UI更新都从EDT调用:
这些是从执行管道调用的侦听器处理程序:
@Override
public void pipelineTaskTerminated(DynamicPipelineEvent event, PipelineTask task) {
publish(task);
}
@Override
public void pipelineTaskUpdated(DynamicPipelineEvent event, PipelineTask task) {
// Here we can publish the update to a task status
publish(task);
}
以下是处理方法:
@Override
protected void process(List<PipelineTask> tasks) {
// Update task listeners on the Event-Dispatch Thread
for (int i = 0; i < tasks.size(); i++){
PipelineTask task = tasks.get(i);
InterfacePipeline pipeline = task.getPipeline();
if (pipeline != null){
task.fireStatusChanged();
}
}
}
除此之外(潜在的信息),对JTree
的调用也不会导致UI的更新,尽管它是从EDT调用的。强制更新树的唯一方法是单击节点本身。可能是一个新线程的问题,但它可能是相关的
我将通过消除线程中任何潜在的UI更新来完成代码和实验,并查看是否可以通过这种方式防止问题。。。请继续关注:)
编辑:即使完全删除这些更新,也会引发相同的异常…可能是错误而不是异常。你查过了吗?请打印堆栈跟踪。@Adrian by Error implementations仅返回
get exception
感谢您的响应;我对命名线程的重要性有点困惑?在我的例子中,我将done()命令包装在一个try-catch块中,它在线程本身或原始EDT调用中都没有被捕获。也就是说,我甚至没有得到一个java.util.concurrent.ExecutionException
您是如何模拟这个异常的,因为所有的异常都被重定向到SwingWorker,所以肯定还有另一个问题,你是否用GCNope杀死了这个线程或一些woodo,我没有杀死它或在它上使用任何实用程序,只是作为SwingWorker运行它,它提供了这个中止的堆栈跟踪。我可以在抛出异常的行的断点处停止;我在OP中添加了堆栈跟踪。只是为了确保,没有应用一些自定义的外观,因为其中一些是invokeAndWait()的必需用法。谢谢,我使用的是自定义L&F,但我只是将其设置为默认值,并得到相同的问题(异常暂停和缺少树更新)。感谢所有的回复!
@Override
public void pipelineTaskTerminated(DynamicPipelineEvent event, PipelineTask task) {
publish(task);
}
@Override
public void pipelineTaskUpdated(DynamicPipelineEvent event, PipelineTask task) {
// Here we can publish the update to a task status
publish(task);
}
@Override
protected void process(List<PipelineTask> tasks) {
// Update task listeners on the Event-Dispatch Thread
for (int i = 0; i < tasks.size(); i++){
PipelineTask task = tasks.get(i);
InterfacePipeline pipeline = task.getPipeline();
if (pipeline != null){
task.fireStatusChanged();
}
}
}
public void taskStatusChanged(PipelineTaskEvent e){
if (model == null) return;
model.nodeStructureChanged(this);
tree.repaint();
}