3

java.awt.Robot を使用してデスクトップリモコンアプリケーションを作成し、正常に動作しています。アプリケーションが別のアプリケーション システムに統合されているため、外部システムからリモート コントロールを開始/停止できるようにしたいのですが、奇妙な問題が見つかりました - ロボットを停止できません。

私はいくつかのことを試しました:スレッド内で実行し(スレッドを停止できるように)、ロボットオブジェクトをnullにし、System.gc()を呼び出すよりも問題はありませんが、まだ実行中のロボットスレッドです(他のすべてが破壊された後) )。デバッグでは、実行中のスレッドが表示されます: Daemon Thread [AWT-Windows] (Running)。

私の問題を再現するコードは次のとおりです。

public class RobotDestroy {

  public static void main(String[] args) {

    try {
        Robot r = new Robot();
    } catch (AWTException e) {
        e.printStackTrace();
    }

    }

}

似たようなことを経験した人はいますか?解決策はありますか?

ありがとう

編集:

以下は、停止可能なスレッドで Robot を実行しているが、Robot インスタンスがまだ実行中の例です。

public class RobotDestroy {

public static void main(String[] args) {

    RobotThread rt = new RobotThread();
    rt.start(); 

    try {
        //do some work before thread shut down
        Thread.sleep(5000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    rt.shutdown();          
}

private static class RobotThread extends Thread {

    public Robot robot;
    volatile boolean alive;

    public RobotThread(){
        try {
            this.robot = new Robot();
            this.alive = true;
        } catch (AWTException e) {
            e.printStackTrace();
        }
    }

    public void run(){

        while(alive){
            System.out.println("alive");
            try{
                robot.delay(5000);
                sleep(1000);

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

    public void shutdown(){
        this.alive = false;
        robot = null;
        System.out.println("shutdown");
    }       
}

}

編集 2

ドクター キラーが提案したことを試してみましたが、これは良い提案ですが、ロボット スレッドはまだ実行中です。それを証明する最善の方法は、ロボット インスタンスの作成前と作成後にスレッドを出力することです。

    Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
    Thread[] threadArray = threadSet.toArray(new Thread[threadSet.size()]);

    for (int i = 0; i < threadArray.length; i++) {
        System.out.println(threadArray[i].getName());
    }

更新: 多くのデバッグの後、問題が java.awt.Robot クラスにないことに気付きました。アプリケーションの終了後も実行されている AWT-Window スレッドを開始するのは java.awt.Toolkit です。Robot オブジェクトには、((ComponentFactory)toolkit).createRobot(this, screen); によって返される RobotPeer (java.awt.peer.RobotPeer) があります。

4

1 に答える 1

0

通常、リモート イベントを受信するスレッドの while(true) ループにフラグを設定するので、while(isAlive) ... read remote event ... リモート イベントが切断された場合は、抜け出します。ループとロボットはコマンドを取得できなくなります。

ロボットが生きているのは、あなたのプログラムがロボットを呼び出し続けているからです...ループを止めるのはあなたです

これも RobotThread に含めます

import java.awt.AWTException;
import java.awt.Robot;
import java.util.LinkedList;

public class RobotDestroy {

    public static void main(String[] args) {
        //Set<Thread> threadSet = Thread.getAllStackTraces().keySet(); Thread[] threadArray = threadSet.toArray(new Thread[threadSet.size()]); for (int i = 0; i < threadArray.length; i++) { System.out.println("Init " + threadArray[i].getName()); }
        RobotThread rt = new RobotThread();
        rt.start(); 

        // Listen to the upcomming commands...and push them to the RobotThread

        rt.shutdown();          
    }

    private static class RobotThread extends Thread {

        public Robot robot;

        public RobotThread(){
            try {
                this.robot = new Robot();
            } catch (AWTException e) {
                e.printStackTrace();
            }
        }

        public void run(){
            Command currentCommand = getNextCommand();
            while(currentCommand.getType() != CommandType.KILL){
                // Process the command no sleep...
                // ...
                // ...

                currentCommand = getNextCommand();
            }

            System.out.println("DIED ");
        }

        private LinkedList<Command> commands = new LinkedList<Command>();

        enum CommandType {
            KILL,
            DO_SOMETHING
        }

        private synchronized Command getNextCommand() {
            while(commands.isEmpty()) {
                try {
                    System.out.println("WAITING");
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return commands.removeFirst();
        }

        public synchronized void pushCommand(Command comm) {
            commands.addLast(comm);
            notify();
        }

        public synchronized void shutdown(){
            commands.clear();
            pushCommand(new Command(CommandType.KILL));
            System.out.println("shutdown");
            //Set<Thread> threadSet = Thread.getAllStackTraces().keySet(); Thread[] threadArray = threadSet.toArray(new Thread[threadSet.size()]); for (int i = 0; i < threadArray.length; i++) { System.out.println("End " + threadArray[i].getName()); }
        }  

        class Command {
            private CommandType cmdType;
            public Command(CommandType type) {
                this.cmdType = type;
            }
            public CommandType getType() { return cmdType; }
        }
    }
}
于 2012-11-22T20:37:41.453 に答える