简体   繁体   English

java.awt.Robot线程无法停止/销毁?

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

I made desktop remote control aplication using java.awt.Robot, and is working fine. 我使用java.awt.Robot制作了桌面远程控制应用程序,并且工作正常。 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). 我尝试了几件事:在线程内运行它(所以我可以停止线程),使机器人对象为null而不是调用System.gc(),但问题不在于引用它的机器人线程仍在运行(在所有其他线程被销毁之后) )。 In debug I can see running thread : Daemon Thread [AWT-Windows] (Running). 在调试中,我可以看到正在运行的线程:守护程序线程[AWT-Windows](正在运行)。

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: 以下是在可以停止但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");
    }       
}

} }

edit 2 编辑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. 更新:经过大量的调试后我意识到问题不在java.awt.Robot类中 - 它是java.awt.Toolkit,它启动应用程序结束后仍在运行的AWT-Window线程。 Robot object has RobotPeer (java.awt.peer.RobotPeer) which is returned by : ((ComponentFactory)toolkit).createRobot(this, screen); Robot对象有RobotPeer(java.awt.peer.RobotPeer),它返回:((ComponentFactory)工具包).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. 通常你会在接收远程事件的线程的while(true)循环中放置一个标志,这样你就会有类似while(isAlive)...读取远程事件......如果远程事件断开连接你就会离开循环和机器人不再获得命令。

The Robot is only still alive because your program keep calling it...your's to stop the loop 机器人只是活着,因为你的程序一直在调用它...你的停止循环

Also include this in your RobotThread 还包括在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; }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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