0

呼び出し/応答 ping のタイムアウトを構築しようとしています。これは、自動接続シーケンスで使用する CommPort を決定するためのものです。byte[]を送信するCALL_SIGNALと、"FU" が返されることを期待しています。これは、どちらが自分のデバイスであるかを判断する方法です。SSCCEは以下です(長くて申し訳ありませんが、これ短縮版です)

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Timer;
import java.util.TimerTask;
import javax.comm.CommPortIdentifier;
import javax.comm.CommPort;
import javax.comm.PortInUseException;
import javax.comm.SerialPort;

public class PingTest {
    public static final long PING_TIMEOUT = 1000; // in millis
    public static final byte[] CALL_SIGNAL = {70, 68, 73, 68};

    public boolean ping(CommPortIdentifier cpi)  {
        System.out.println("Pinging " + cpi.getName());
        CommPort port = null;
        InputStream input = null;
        OutputStream output = null;

        //Initialization test
        try {
            port = cpi.open("pingTest", 50);
            input = port.getInputStream();
            output = port.getOutputStream();
        } catch (PortInUseException ex) {
            if (cpi.getCurrentOwner().startsWith("pingTest")) {
                System.out.println("Port already owned by this application.");
                return true;
            }
            return false;
        } catch (Exception ex) {
            try {
            port.close();
            } catch (NullPointerException e) {
            }
            System.out.println("Failed initialization test.");
            System.err.println(ex);
            return false;
        }
        System.out.println("Passed initialization test."); 

        //Call and response test
        final Stop stop = new Stop();
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {

            @Override
            public void run() {
                System.out.println("Stop timer triggered.");
                stop.shouldStop = true;
            }
        }, PING_TIMEOUT);
        try {
            System.out.println("Writing...");
            output.write(CALL_SIGNAL);
            System.out.println("Reading...");
            boolean waitForF = true;
            while (!stop.shouldStop && !stop.didPass) {
                if (waitForF) {
                    if ((byte) 'F' == input.read()) {
                        waitForF = false;
                    }
                } else {
                    System.out.println('F');
                    if ((byte) 'U' == input.read()) {
                        System.out.println('U');
                        stop.didPass = true;
                    } else {
                        System.out.println();
                        waitForF = true;
                    }
                }
            }
        } catch (IOException ex) {
            System.out.println("Failed I/O test.");
            return false;
        } finally {
            port.close();
        }

        if (stop.didPass) {
            System.out.println("Successful ping.");
            return true;
        }
        System.out.println("Failed call and response test.");
        return false;
    }

    public static void main(String[] args) {
        PingTest pinger = new PingTest();
        Enumeration<CommPortIdentifier> ports = CommPortIdentifier.getPortIdentifiers();
        boolean trigger = true;
        String name = null;
        while (trigger && ports.hasMoreElements) {
            CommPortIdentifier cpi = ports.nextElement();
            name = cpi.getName();
            trigger = !ping(cpi);
        }
        if (trigger) {
            System.out.println("Found it. It is " + name);
        } else {
            System.out.println("Not Found");
        }
    }
}

class Stop {
    boolean shouldStop = false;
    boolean didPass = false;
}

私の出力は次のとおりです。

Pinging COM1
Passed initialization test.
Writing...
Reading...
Stop timer triggered.

そして、アプリケーションがフリーズします。while ループを で停止しようとすると問題がありTimerますか?

4

2 に答える 2

1

読み取りがブロックされています。タイムアウトを使用する必要があります

于 2012-06-04T20:49:51.043 に答える
0

同期せずに、異なるスレッドから同時に共有状態 (shouldStopおよび変数)にアクセスしています。didPass他のスレッドが書き込んだものを確実に読み取りたい場合は、すべてのアクセスを同期する必要があります。

したがって、これらの変数を取得および設定するメソッドを追加し、それらのメソッドを同期させるか、各変数が他の変数とは異なる情報を表し、独立して読み書きできる場合は、それらの変数を揮発性にします。

3 つ目の方法 (volatile ソリューションと同じ条件下でのみ有効) は、ブール変数の代わりに AtomicBoolean 変数を使用することです。

于 2012-06-04T20:46:47.320 に答える