3

I have been working with Java threads in order to provide a GUI platform for running processes in a pipeline. I've managed to work through a number of issues with SwingWorker, but this one is seemingly incomprehensible.

My SwingWorker looks like:

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); } }; 

I use this to run a Java process; a simplified version of the launching code is:

try{ Class<?> target_class = Class.forName(main_class); CommandInstance instance = (CommandInstance)target_class.newInstance(); CommandFunctions.ProcessState state = instance.execute(args); }catch (InvocationTargetException e){ throw new PipelineException("Java process '" + this.getName() + "." + uid + "' encountered exception: " + e.getCause().getMessage()); }catch (Exception e){ throw new PipelineException("JavaProcess encountered exception invoking target: " + e.getMessage()); } 

The process itself has a try-catch block around code which loads some data from a file. However, despite being wrapped in two layers of try-catch blocks (actually three, if you count the done() method), when the loader throws an Exception it prints a stack trace, the Exception is not caught, and the SwingWorker thread hangs (the code halts so I can no longer force an interrupt).

This sort of Exception hanging has occurred in other circumstances as well; most puzzlingly, in other -- seemingly identical -- cases the Exception is caught and the thread exits gracefully.

I haven't been able to find much about this online, although I'll continue to search. I am no expert in Swing threading, so I was hoping someone might have an insight about this sort of issue. I'd love it to be a very stupid error on my part :)

EDIT: @Adrian, here is the stack trace. It seems to stall half way... very strange:

java.io.EOFException at java.io.RandomAccessFile.readFully(RandomAccessFile.java:399) at mgui.io.standard.nifti.Nifti1Dataset.readVolBlob(Nifti1Dataset.java:2179) at mgui.io.standard.nifti.Nifti1Dataset.readDoubleVol(Nifti1Dataset.java:1916) at mgui.io.standard.nifti.NiftiVolumeLoader.setGrid3DBlocking(NiftiVolumeLoader.java:186) at mgui.io.domestic.shapes.VolumeFileLoader.setGrid3D(VolumeFileLoader.java:237) at mgui.io.domestic.shapes.VolumeFileLoader.getGrid3D(VolumeFileLoader.java:139) at mgui.io.domestic.shapes.VolumeFileLoader.getGrid3D(VolumeFileLoader.java:97) at minc.MincFunctions.create_volume_atlas_masks(MincFunctions.java:5240) at minc.MincFunctions.run_command(MincFunctions.java:153) at mgui.command.CommandInstance.execute(CommandInstance.java:87) at mgui.pipelines.JavaProcess.run(JavaProcess.java:141) at mgui.pipelines.PipelineFunctions.launchBlockingPipelineProcess(PipelineFunctions.java:238) at mgui.pipelines.PipelineFunctions.launchPipelineProcess(PipelineFunctions.ja 

EDIT2: Debugging in Eclipse, I can halt at a breakpoint on the line where it is thrown (well, one step before); the stack trace at that point is:

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 
2
  • maybe it's an Error not an Exception. Have you checked? Print the stack trace please. Commented Jan 10, 2012 at 21:26
  • @Adrian by wrong implementations returns only Got exception Commented Jan 10, 2012 at 22:04

3 Answers 3

2

yes is possible take Exception(s) from SwingWorker's methods done(), but required strictly naming every thread, more in this thread, especially answer by @trashgod, and I haven't found another possibility of how to it another way

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for the response; I am a bit confused about the importance of naming a thread? In my case I have the done() command wrapped in a try-catch block and it is not being caught either in the thread itself or the original EDT call.
i.e., I am not even getting a java.util.concurrent.ExecutionException
how did you simulate this exception, because all Exeptions are redirected to the SwingWorker, there must be another issue, did you kill this thread or some woodo with GC
Nope, I didn't kill it or use any utilities on it, just ran it as a SwingWorker and it delivered this aborted stack trace. I can halt at a breakpoint right at the line where the Exception is thrown; I added that stack trace to the OP.
0

I solved a similar table problem by not interfering when the AWT thread was painting the UI. I used invokeLater() to synchronize my thread with the UI thread.

See EventQueue for more details.

Comments

0

@Adrian, thanks for the suggestion; I do not think I am making any UI updates directly from the SwingWorker thread; I do make updates to JTree nodes to indicate the success or failure of a process, but I use the publish/process mechanism for this, which should ensure that all UI updates are called from the EDT:

These are listener handlers called from the executing pipeline:

@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); } 

And here is the process method:

@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(); } } } 

Finally, here is how the JTree handles the event:

public void taskStatusChanged(PipelineTaskEvent e){ if (model == null) return; model.nodeStructureChanged(this); tree.repaint(); } 

As a (potentially informative) aside, this call to the JTree also does not result in an update of the UI, despite its being called from the EDT. The only way to force the tree to update is by clicking on the node itself. Possibly an issue for a new thread, but it may be related.

I'll go through the code and experiment by eliminating ANY potential UI updates from the thread, and see if the problem can be prevented that way... stay tuned :)

EDIT: Even removing these updates altogether I get the same Exception thrown...

2 Comments

just for ensure, isn't there applied some of Custom Look and Feel stackoverflow.com/a/3954646/714968, for some of them is required usage of invokeAndWait()
Thanks, I am using a custom L&F, but I just set it to the default and get the same issues (both the Exception stalling and the lack of tree updates). Appreciate all the responses though!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.