Nixsy
Nixsy

Reputation: 33

JAVA - External exe locking when called from launcher

I have been trying to use a custom output stream to display the output from an executable on a Jtext area.

The executable is called from a button via

        try {
            Process p = Runtime.getRuntime().exec("cgminer.exe" + " -o " + Infos.Address + ":" + Infos.Port + " -u " + Infos.User + " -p " + Infos.Password);
            p.waitFor();

            String line;

            BufferedReader error = new BufferedReader(new InputStreamReader(p.getErrorStream()));
            while((line = error.readLine()) != null){
                System.out.println(line);
            }
            error.close();

            BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
            while((line=input.readLine()) != null){
                System.out.println(line);
            }

            input.close();

            OutputStream outputStream = p.getOutputStream();
            PrintStream printStream = new PrintStream(outputStream);
            printStream.println();
            printStream.flush();
            printStream.close();
        }
            catch (Exception e) {
                // ...
              }
    }

}

and then the output is directed to the jtext with

public class CustomOutputStream extends OutputStream {
    private JTextArea textArea;

    public CustomOutputStream(JTextArea textArea) {
        this.textArea = textArea;
    }

    @Override
    public void write(int b) throws IOException {
        textArea.append(String.valueOf((char) b));
        textArea.setCaretPosition(textArea.getDocument().getLength());
    }
}

My problem is when I call the first class the button locks and no output makes it to the jtext. It is only when I force close the cgminer that the output appears.

Any help is really appreciated as this has my brain warped.

Upvotes: 1

Views: 172

Answers (1)

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285430

My problem is when I call the first class the button locks and no output makes it to the jtext. It is only when I force close the cgminer that the output appears.

This is a classic symptom of tying up the Swing event thread. When you run a long-running piece of code on the Swing event thread (also known as the EDT or Event Dispatch Thread), you prevent the thread from doing its chores including painting the GUI and interacting with the user, effectively "freezing" the GUI.

The solution is not to comment the waitFor() as another suggested, but rather to run it and any other blocking code in backgrounds thread such as a SwingWorker. When you do this, make sure to take care to only update your Swing GUI on the event thread. The SwingWorker has a built-in way to do this via its publish and process methods.

For details on this, please check out Concurrency in Swing

You will also need to do more threading since some lines of your code are blocking and will prevent lines down stream from running until they unblock, but by then all the important action is done. For instance these block:

// this blocks
p.waitFor();

// this blocks both times you use it
while((line = error.readLine()) != null){
  System.out.println(line);
}

Upvotes: 3

Related Questions