2

我需要修改 RXTX“基于事件的双向通信”(请参阅​​ http://rxtx.qbang.org/wiki/index.php/Event_based_two_way_Communication),以便我能够将特定响应写回串行设备关于其上一条消息。

我通过发送第一个命令开始通信。到目前为止一切正常。现在我从串行设备得到答案。我用进一步的命令对答案做出反应。但是我不能再写了,因为写线程已经结束了。

有人知道如何处理吗?非常感谢!

public class TwoWaySerialComm {
    public TwoWaySerialComm() {
        super();
    }

public static void main(String[] args) {
        try {

            // 0. call connect()
            (new TwoWaySerialComm()).connect("COM1");

        } catch (Exception e) {
            e.printStackTrace();
        }
}

void connect(String portName) throws Exception {

                // 1. get CommPortIdentifier, open etc...

                // 2. then do
                InputStream in = serialPort.getInputStream();
                OutputStream out = serialPort.getOutputStream();

                // 4. start writer thread
                (new Thread(new SerialWriter(out))).start();

                // 5. instantiate SerialReader 
                serialPort.addEventListener(new SerialReader(in));
                serialPort.notifyOnDataAvailable(true);

}

public static class SerialWriter implements Runnable {

        OutputStream out;

        public SerialWriter(OutputStream out) {
            this.out = out;
        }

        public void run() {
            try {

                // establish a communication by sending the first command. the serial device will answer!   
                String toSend = "blablabla";
                this.out.write(toSend);

                // thread ended???

}

public static class SerialReader implements SerialPortEventListener {

        private InputStream in;

        public SerialReader(InputStream in) {
            this.in = in;

        }

        public void serialEvent(SerialPortEvent arg0) {

            // event occurs beacause device answers after writing.

            int data;

            try {

                StringBuffer sb = new StringBuffer();
                String LineOfData=null;

                while ((data = in.read()) > -1) {

                    if (data == '\n') {
                        break;
                    }

                    sb.append(Integer.toHexString(data));
                    LineOfData = sb.toString();

                }
                // I store the answer and send it to an EventIterpreter. Regarding the answer, it creates an appropriate response itselves.
                EventInterpreter e = new EventInterpreter(LineOfData);  
                String result = e.getData

HERE >> // Now I want to send this response back to the device. But the thread is already ended.


            } catch (IOException e) {
                e.printStackTrace();
                System.exit(-1);
            }
        }

  }

}
4

1 回答 1

1

不要让运行 SerialWriter 的线程完成。

while (System.in.read() != -1)在原始示例中run(),您会注意到SerialWriter. 这很重要。运行它的线程阻塞read()然后,一旦它有一些数据要读取,它就会做一些工作,然后循环回到同一个位置,等待更多的输入。这是一个在正常情况下不应该完成的线程。

至关重要的是,编写器的非守护线程正在运行这一事实意味着,当您的主线程(JVM 用来启动程序的线程)用完 connect() 方法中的语句时,JVM 不会立即关闭.

串口在它自己的线程上回叫你

serialPort调用您的侦听器的public void serialEvent(SerialPortEvent)方法时,它会在自己的线程上执行此操作

您现在的任务是尽可能快地脱离 serialPort 的线程。几乎,读取数据,将其粘贴在缓冲区中,您的另一个线程可以在空闲时对其进行解析和操作,同时让 serialPort 继续处理通信。你当然不应该尝试在它自己的线程上调用你时写入串行端口。它没有任何状态回复你,因为它在等你完成!

您希望您的“作家”线程“等待”,直到有东西要回复

您可以通过提供“锁定”对象来进行安排。由于这些是现代时代,请使用:

import java.util.concurrent.locks.*;

// accessible to both reader and writer
...
Lock lock = new ReentrantLock();
Condition dataAvailable = lock.newCondition();
byte[] buffer;

// in the writer
...
public void run() {
    while(true) {
        lock.lock();
        try {
            dataAvailable.await();  // writer thread dozes
            doStuff(buffer);
        } finally {
            lock.unlock();
        }
    }
}


// in the reader
...
public void onEvent() {
    lock.lock();
    try {
        buffer = readData();
        dataAvailable.signal();   // writer thread wakes up
    } finally {
        lock.unlock();
    }
}

读一本关于并发的好书

并发是棘手的。您需要阅读Java Concurrency in Practice

当您尝试剪切和粘贴上面的代码示例时,您会注意到Condition#await()throws InterruptedException。究竟该怎么做超出了这个答案的范围。:-) 这while(true)也有点狡猾。

于 2012-12-05T14:58:16.877 回答