简体   繁体   中英

java.awt.Robot thread can't be stopped/destroyed?

I made desktop remote control aplication using java.awt.Robot, and is working fine. Application is integrated in another application system so I want to be able to start/stop remote control from outer system and I found strange problem - I can't stop Robot.

I tried several things: running it inside thread (so I can stop thread), making robot object null and than calling System.gc() but the problem isn't with reference it's robot thread that is still running (after all others are destroyed). In debug I can see running thread : Daemon Thread [AWT-Windows] (Running).

Here is code that will reproduce my problem:

public class RobotDestroy {

  public static void main(String[] args) {

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

    }

}

Has anybody expirienced somthing similar ? Any solutions ?

thanks

edit:

Here is example of running Robot in a thread that can be stopped but a Robot instance is still running:

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");
    }       
}

}

edit 2

I tried what doctor killer suggested and although it is a good suggestion Robot thread is still running. Best way to prove it is to print-out threads before creating robot instance and after:

    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());
    }

UPDATE: After a lot of debugging I realized that problem isn't in java.awt.Robot class - it is java.awt.Toolkit that starts AWT-Window thread that remains running after application ends. Robot object has RobotPeer (java.awt.peer.RobotPeer) which is returned by : ((ComponentFactory)toolkit).createRobot(this, screen);

usually you would put a flag in your while(true) loop of the thread that receive the remote events so you would have something like while(isAlive) ... read remote event ... if remote event is disconnect you then get out of the loop and the robot would not get commands anymore.

The Robot is only still alive because your program keep calling it...your's to stop the loop

Also include this in your 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; }
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM