ImageJ/FIJI crash on IJ.run(...)

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

ImageJ/FIJI crash on IJ.run(...)

AJBell
Dear list,

I have written a set of PlugIns for our image analysis which make use of Threading using the RunnableJob method. The scripts work as intended when launched from the ImageJ or Fiji plugings menu and from the plugins editor. When I try to run the plugin from a button in a Frame, the program hangs.

By excising bits of code, I've narrowed the problem down to several commands, including:

IJ.run("Set Measurements...")
imp.close();

These are commands I have used before with no problems and I cannot see why the program only hangs when started from a button, but not from the main menu.

The following code reproduces the arrangement of the code I have, and gives the same fault. When the IJ.run("set Measurements...") is commented out (line 53, ThreadTest Class), the program runs fine; when it is included, the program crashes. Any suggestions as to what is happening or why would be greatfully received.

Andrew Bell
Research Associate
University of Leicester

//Frame class:
import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
import ij.plugin.frame.*;
import java.awt.event.*;

public class ButtonFrame extends PlugInFrame implements ActionListener {

        public ButtonFrame() {
                super("ButtonFrame");
                Button ta = new Button("Start");
                ta.addActionListener(this);
                add(ta);pack();show();
        }
        public void actionPerformed(ActionEvent e){
                IJ.log("Button Clicked");
                ThreadTest tt = new ThreadTest();
                tt.run("");
        }
}

//Thread class:
import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
import ij.plugin.*;

public class ThreadTest implements PlugIn {

        public RunnableJob runnableJob = new RunnableJob();
        public String[] str_list = {"Apples","Stairs"};

        public void run(String arg){
               
                for(int i=0; i<str_list.length;i++){
                        try{
                                Thread t = new Thread(runnableJob, str_list[i]);
                                t.start();
                                t.join();
                        }catch (InterruptedException ex) {
                                IJ.showMessage("Error",""+ex);
                        }

                }
                IJ.log("Complete");
        }// end of ThreadTest run

        public class RunnableJob implements Runnable {

                public String name;

                public void run() {
                        Thread thread = Thread.currentThread();
                        name = thread.getName();
                       
                        try {
                                TestFunction tf = new TestFunction();
                                tf.run(name);
                       
                        } catch (Exception e) {
                                IJ.showMessage("Error",""+e);
                        }
                }

        } //end of RunnableJob

        public class TestFunction {

                public void run(String arg){
                        try{
                                int x = (int)(Math.random() * 1000);
                                Thread.sleep(x);
                                IJ.log(arg+" "+x+" ms delay");
                                //IJ.run("Set Measurements...", "area perimeter fit feret's integrated display redirect=None decimal=3");
                        } catch(Exception e){
                                IJ.log(""+e);
                        }
                }
        }// end of TestFunction
} //class end
Reply | Threaded
Open this post in threaded view
|

Re: ImageJ/FIJI crash on IJ.run(...)

dscho
Hi Andrew,

On Tue, 18 Feb 2014, AJBell wrote:

> I have written a set of PlugIns for our image analysis which make use of
> Threading using the RunnableJob method. The scripts work as intended
> when launched from the ImageJ or Fiji plugings menu and from the plugins
> editor.  When I try to run the plugin from a button in a Frame, the
> program hangs.


I am glad that the program does not crash Fiji -- as suggested by the
mail's subject. Please be careful when describing software behavior (a
crash means that the program quits unexpectedly without giving the user a
chance to save her data, something quite different from a hang that does
not allow the user to interact with the program anymore).

> Thread t = new Thread(runnableJob, str_list[i]);
> t.start();
> t.join();

The "join()" is the problem.

Remember: your button press is detected and handled on the event dispatch
thread (EDT). It calls actionPerformed() eventually, still on the EDT.
Then you start a thread -- this thread will run parallel to the EDT.

But now "join()" is called -- waiting for the other thread to return. The
"join()" call is run *on the EDT*, blocking event dispatching until
further notice.

Now, that usually only makes the GUI unresponsive until the started thread
is done.

Except if that other thread tries to send an event itself -- which
imp.close() does: it needs to close the window, and that is done via
sending a WindowClosingEvent and then WindowCloseEvent.

Those messages are sent, and then the other thread *waits* until the
events are handled. Those events will need to be handled on the EDT,
though, and that thread is blocked.

Basically, the EDT is blocked waiting for the other thread while the other
thread says: no, you first. It's like Mid-West traffic: trying to be
polite and let the other go first, everybody just sits and waits.

A better way would be to design the program with less need to control: let
it spawn the threads and return. If something needs to be done in response
to those threads returning, it should be done at the end of those threads.

In general, it is a very good idea to spend as little time as possible
blocking the EDT. A good practice is to implement the real action as a
Runnable that the event handler will wrap in a Thread and start() it
("fire 'n forget" style).

Ciao,
Johannes

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html