java - метод возврата строки вызывается до того, как какое-либо значение будет присвоено строке - PullRequest
0 голосов
/ 01 марта 2012

Мое приложение должно читать и записывать в последовательный порт.Данные читаются в EventListener класса PortReader.Я хочу присвоить эти данные глобальной переменной String (private String sPortReaderString) для дальнейшего использования.Глобальная строковая переменная должна возвращать свое значение, используя метод getPortReader (), который просто возвращает строку sPortReaderString.В JFrame приложения я открываю соединение через последовательный порт, отправляю команду, для которой я автоматически получаю ответ от последовательного устройства, и отображаю вывод ответа в метке.Проблема в том, что метка всегда пуста, так как sPortReaderString, возвращаемая из getPortReader (), не имеет ничего назначенного ей.Я очень уверен, что sPortReaderString получает значение в EvenListener.Похоже, проблема в том, что метод getPortReader () в JFrame вызывается до того, как какое-либо значение успеет присвоиться sPortReaderString.Пожалуйста, посмотрите на мой отупут и приведенный ниже код:

Ниже приведен вывод, который я получаю:

sPortReaderString:
PortReader

Краткий пример portsMethod в JFrame:

public class MyJFrame extends javax.swing.JFrame {

    public MySerialPort msp = new MySerialPort();   

    public MainJFrame() {
        portsMethod();
    }

    private void portsMethod() {

        msp.getPortNames();//Gets the name of the port (COM1 in my case)
        msp.openPort();//Opens COM1 port
        msp.getFirmwareVersion();//Prompts for device firmware version by sending a string command
        msp.getPortReader();//Reads the reply from device

    }

}

Ниже приведен пример моего класса последовательного порта:

public class MySerialPort {

    private SerialPort serialPort;
    private int iBaudRate = SerialPort.BAUDRATE_57600;
    private int iDataBits = SerialPort.DATABITS_8;
    private int iStopBits = SerialPort.STOPBITS_1;
    private int iParity = SerialPort.PARITY_NONE;
    private String sPortName;
    private String sPortReaderString = "";
    private StringBuilder sbPortReaderString = new StringBuilder();

    public void getFirmwareVersion() {
        sendPortCommand("<FirmVer>\r\n");
    }

    public void clearPortReader() {
        sbPortReaderString.setLength(0);
    }

    public String getPortReader() {
        System.out.print("sPortReaderString: " + sPortReaderString);
        return sPortReaderString;
    }

    public void getPortNames() {
        String[] sPorts = SerialPortList.getPortNames();
        sPortName = sPorts[0];
    }

    public void openPort() {

        serialPort = new SerialPort(sPortName);

        try {

            if (serialPort.openPort()) {

                if (serialPort.setParams(iBaudRate, iDataBits, iStopBits, iParity)) {

                    serialPort.addEventListener(new PortReader(), SerialPort.MASK_RXCHAR
                            | SerialPort.MASK_RXFLAG
                            | SerialPort.MASK_CTS
                            | SerialPort.MASK_DSR
                            | SerialPort.MASK_RLSD);

                } else {
                    serialPort.closePort();
                }

            } else {}
        } catch (SerialPortException | HeadlessException ex) {}
    }

    private void sendPortCommand(String sSendPortCommand) {

        if (sSendPortCommand.length() > 0) {
            try {
                serialPort.writeBytes(sSendPortCommand.getBytes());
            } catch (Exception ex) {}
        }
    }

    private class PortReader implements SerialPortEventListener {

        private String sBuffer = "";

        @Override
        public void serialEvent(SerialPortEvent spe) {

            if (spe.isRXCHAR() || spe.isRXFLAG()) {

                if (spe.getEventValue() > 0) {

                    try {

                        //Read chars from buffer
                        byte[] bBuffer = serialPort.readBytes(spe.getEventValue());
                        sBuffer = new String(bBuffer);

                        SwingUtilities.invokeAndWait(
                                new Runnable() {

                                    @Override
                                    public void run() {
                                        sbPortReaderString.append(sBuffer);
                                    }
                                });

                        sPortReaderString = new String(sbPortReaderString);
               //if I print sPortReaderString in here it is not blank and has the correct value

                        System.out.print("PortReader");

                    } catch (SerialPortException | InterruptedException | InvocationTargetException ex) {
                    }
                }
            }
        }
    }
}

1 Ответ

2 голосов
/ 01 марта 2012

Мне кажется довольно логичным:

У вас есть первый метод обработки событий в EDT, который получает версию прошивки, а затем получает считыватель портов.Получение версии прошивки приводит к получению события в другом потоке (и, следовательно, параллельно с выполнением portsMethod() в EDT).

Код обработки события вызывает SwingUtilities.invokeAndWait().Таким образом, этот вызов ожидает завершения обработки первого события methd, а затем добавляет полученную строку к sbPortReaderString.Таким образом, это добавление выполняется после завершения portsMethod.

Последовательный порт предлагает механизм, основанный на событиях.Я бы просто использовал его для передачи события одному или нескольким слушателям в EDT:

// accessed only from the EDT
private List<MyPortListener> portListeners = new ArrayList<MyPortListener>();

public void addMyPortListener(MyPortListener listener) {
    portListeners.add(listener);
}

public void removeMyPortListener(MyPortListener listener) {
    portListeners.remove(listener);
}

... 

    @Override
    public void serialEvent(SerialPortEvent spe) {
        ...
        final String receivedString = ...;
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                for (MyPortListener listener : portListeners) {
                    listener.stringReveivedFromSerialPort(receivedString);
                }
            }
        });
    }

Примечание: ваш код сложен для понимания главным образом потому, что ваши переменные и методы имеют неправильные имена.

...