The code does not work during normal operation, but it works in debug (eclipse)

I am really confused by this: some of my code does not work when I run my program, usually in eclipse, but it works when I run each step separately, using debug mode.

code:

public void showConnectDialog() { ConnectDialog connectDialog = new ConnectDialog(); connectDialog.setVisible(true); //Until here, code runs while(! connectDialog.getConnected()) {}; //The next line does only run in debug JOptionPane.showMessageDialog(connectDialog, "Connected", "Connected", JOptionPane.INFORMATION_MESSAGE); } 

Connector (starts (as a thread) as soon as the user clicks "connect" in the dialog box):

 private class ServerConnector implements ActionListener, Runnable { @Override public void actionPerformed(ActionEvent e) { if (! IP_field.getText().equals("")) { if (! isConnecting) { new Thread(new ServerConnector(), "ServerConnector").start(); } } else { JOptionPane.showMessageDialog(dialog, "Enter an IP address", "Enter IP", JOptionPane.WARNING_MESSAGE); } } @Override public void run() { try { setConnecting(true); Socket socket = connect(); if (socket != null) { ObjectOutputStream oOut = new ObjectOutputStream(socket.getOutputStream()); ObjectInputStream oIn = new ObjectInputStream(socket.getInputStream()); if (login(oOut, oIn)) { isConnected = true; setConnecting(false); } else { socket.close(); } setConnecting(false); } } catch (RSPException e) { e.printStackTrace(); System.exit(1); } catch (Exception e) { //If an exception occurs, setConnecting() will be true. This //not good, so it has to be set to false e.printStackTrace(); setConnecting(false); } } private boolean login(ObjectOutputStream oOut, ObjectInputStream oIn) throws ClassNotFoundException, IOException, RSPException { //Send login request action: oOut.writeObject(new LoginAction(ActionSender.CLIENT, getID(), getPassword())); Object obj = oIn.readObject(); if (obj instanceof LoginActionResult) { LoginActionResult result = (LoginActionResult) obj; if (result.getResult() == LoginResults.SUCCES) { return true; } else if (result.getResult() == LoginResults.FAIL_ON_ID) { JOptionPane.showMessageDialog(dialog, "Invalid password or ID", "Can't login", JOptionPane.ERROR_MESSAGE); return false; } else if (result.getResult() == LoginResults.FAIL_ON_PASSWORD) { JOptionPane.showMessageDialog(dialog, "Invalid password or ID", "Can't login", JOptionPane.ERROR_MESSAGE); return false; } else if (result.getResult() == LoginResults.SERVER_FULL) { JOptionPane.showMessageDialog(dialog, "Couldn't connect: \n" + "Server is full", "Failed to connect", JOptionPane.WARNING_MESSAGE); return false; } else { return false; } } else { System.out.println(obj); throw new RSPException("Server is not following the protocol."); } } private void setConnecting(boolean connecting) { if (connecting) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { connectButton.setEnabled(false); } }); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { connectButton.setText("Connecting..."); } }); } else { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { connectButton.setText("Connect"); } }); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { connectButton.setEnabled(true); } }); } isConnecting = connecting; } private String getAddressFromTextField() { return IP_field.getText(); } private InetAddress getInetAddress(String fullAddress) { try { if (fullAddress.contains(":")) { String[] splitAddress = fullAddress.split(":"); return InetAddress.getByName(splitAddress[0]); } else { return InetAddress.getByName(fullAddress); } } catch (UnknownHostException e) { return null; } } private int getPort(String fullAddress) { try { String[] splittedAddress = fullAddress.split(":"); return Integer.valueOf(splittedAddress[1]); } catch (NumberFormatException ex) { return -1; } catch (NullPointerException | ArrayIndexOutOfBoundsException | PatternSyntaxException ex) { //Returning default port value: 25566, because no port was given return 25566; } } @SuppressWarnings("resource") private Socket connect() { Socket socket = null; InetAddress address = null; if ((address = getInetAddress(getAddressFromTextField())) == null) { return null; } int port = getPort(getAddressFromTextField()); try { socket = new Socket(address, port); } catch (ConnectException e ) { Socket retrySocket = null; if ((retrySocket = retryConnect(address, port)) == null) { JOptionPane.showMessageDialog(dialog, "Connection timed out", "Failed to connect", JOptionPane.ERROR_MESSAGE); setConnecting(false); } else { socket = retrySocket; } } catch(IOException e) { e.printStackTrace(); } return socket; } private Socket retryConnect(InetAddress address, int port) { Thread waitThread = new Thread(new Runnable() { @Override public void run() { try { //Will wait 15(000) (milli)seconds before stopping with //trying to connect. //One second (1000 millis) is for debugging and testing Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }); waitThread.start(); while (waitThread.isAlive()) { try { return new Socket(address, port); } catch (ConnectException e) { //Do nothing, will re-attempt to connect. } catch (IOException e) { e.printStackTrace(); } } return null; } private String getID() { return ID_field.getText(); } private String getPassword() { if (getID().equals("master")) { return "masterPassword"; } else { return new String(passwordField.getPassword()); } } } 

getConnected() returns true as soon as it connects to the server. The connector runs on a separate thread.

EDIT : I tried putting the code in the getConnected() while block, and then it works. Why does it work then and not otherwise?

+6
source share
3 answers

I had the same problem, but with some additional specs. The code worked fine in 32 bits, but I had this problem on 64-bit (I use my own library, so I need to support both).

The solution I found is to add Thread.sleep () to the while loop. I don’t know why this works, so your assumption is as good as mine.

A better solution would probably be to implement an observer pattern instead of an infinite loop. But this will require some re-factoring.

+3
source

I had a very similar problem with a while loop that did not start, and this loop was my main routine. As I got the loop to run, it was that the first thing that was done in the loop was a dream:

  try {Thread.sleep(0);} catch (Exception e) {e.printStackTrace();} 

That was enough to make things work out.

+2
source

Using Thread.sleep() , as other answers suggested, should solve the problem, but this is not a very good approach. Instead, we should use Thread.yield() .

Why yield and not sleep ?

See: The difference between Thread.Sleep (0) and Thread.Yield () and Are Thread.sleep (0) and Thread.yield () equivalent?

Why does it work?

When we just start threads, the OS puts them in a state of "inaction", and when awakening is expected, this is not so. On the other hand, in debug mode, we have a controlled environment. The OS has little control over this, since everything is moving in stages, slowly. If we run debugging several times without any breakpoints, after several successful runs we should see the same effect.

0
source

Source: https://habr.com/ru/post/947130/


All Articles