使用SwingWorker读取串口无输出,添加弹窗后方法仍未执行求助
嘿,我帮你拆解下当前遇到的问题:加了JOptionPane后只看到"Reading"和"Done",中间的端口检测、getPortText都没执行,大概率是后台线程的逻辑被异常吞了,或者串口枚举本身出了问题,咱们一步步来排查:
1. 先把SwingWorker的异常抓出来!
SwingWorker的doInBackground方法如果抛出未捕获的异常,不会主动弹错误,只会默默终止线程——这就是你看不到中间输出的核心原因之一。赶紧给你的Worker加个try-catch,把异常打出来:
class SerialWorker extends SwingWorker<Void, String> { @Override protected Void doInBackground() throws Exception { publish("Reading"); try { // 把你的串口检测、读取逻辑全放进try块里 SerialPort[] availablePorts = SerialPort.getCommPorts(); publish("检测到可用端口数:" + availablePorts.length); if (availablePorts.length > 0) { // 这里调用你的getPortText String portInfo = getPortText(availablePorts); publish(portInfo); // 后续的串口读取逻辑... } } catch (Exception e) { publish("后台线程出错:" + e.getMessage()); e.printStackTrace(); // 控制台打印完整异常栈,这是排查关键! } publish("Done"); return null; } @Override protected void process(List<String> chunks) { // 把所有publish的消息打印到控制台(或者UI组件) for (String msg : chunks) { System.out.println(msg); } } } // 启动Worker的正确方式:必须调用execute(),绝对不能直接调doInBackground! new SerialWorker().execute();
划重点:一定要用
execute()启动Worker,直接调用doInBackground()会让代码跑在EDT线程,完全失去后台线程的意义,还可能阻塞UI。
2. 单独测试串口枚举,排除库的问题
你说可用端口的IF块没执行,先脱离SwingWorker,单独测试fazecast的端口枚举功能,确认库本身能识别到串口:
public static void testPortScan() { SerialPort[] ports = SerialPort.getCommPorts(); System.out.println("扫描到的串口总数:" + ports.length); for (SerialPort port : ports) { System.out.println("串口名称:" + port.getSystemPortName()); // 顺便测试你的getPortText System.out.println("串口详情:" + getPortText(port)); } } // 直接在main方法里跑这个测试 public static void main(String[] args) { testPortScan(); }
如果这里输出0个端口,那问题出在串口本身或者库的配置:
- Windows:去设备管理器看串口是否存在,有没有被其他程序占用
- Linux/macOS:把当前用户加入
dialout(Linux)或uucp(macOS)组,重启后再试(串口设备需要权限访问) - 确认你用的fazecast SerialComm JAR是最新版本,没有依赖缺失
如果这里能正常输出端口,那回到SwingWorker里检查逻辑:是不是变量名写错了?或者IF判断的条件写反了?
3. 检查getPortText的调用逻辑
确认你在doInBackground里确实调用了getPortText,而且调用条件满足:
- 比如是不是写了
if (availablePorts == null)而不是if (availablePorts.length > 0)? - 如果
getPortText是实例方法,有没有用对对象调用?比如是不是误写成了静态调用? - 可以在
getPortText方法开头加一句System.out.println("getPortText被调用了!"),直接确认是否执行到这里。
4. 去掉那个阻塞EDT的JOptionPane
你加的JOptionPane.showConfirmDialog会阻塞EDT线程(UI线程),虽然理论上不影响后台线程,但可能干扰你对Worker执行状态的判断。先把它去掉,用控制台输出或者UI组件(比如JTextArea)来显示日志,避免阻塞EDT。
按照这个顺序排查,应该能很快找到问题所在——大概率是后台线程抛了异常没被捕获,或者串口枚举需要权限。
内容的提问来源于stack exchange,提问作者J Lag

