2009-04-16 77 views
0

我一直在问最近一个项目的许多问题。这里是我所处的场景,任何帮助或正确的方向将有助于很多...EDT与主线程之间的通信

这是一个使用服务器和多个客户端构建的网络程序。每个客户端都有一个GUI,它必须根据服务器发送的命令行事。每个客户都被包装在名为Player的类中。这个Player有一个GUI(扩展JFrame)和一个主要方法,并且服务器只有一个主要方法(没有GUI)。起初,这个类在主线程中创建这样的:

EventQueue.invokeLater(new Runnable() 
{ 
    public void run() 
    { 
     new Player().setVisible(true); 
    } 
}); 

这是工作的罚款,直到我意识到整个Player类在EDT现在正执行。因此,当我等待来自服务器的命令时,整个GUI将锁定,直到发送该命令并执行适当的操作。正如你可以想象的那样,这是一个可怕的设计,并且被证明是编码环境的一个真正的痛苦,当你每次想要检查某些东西时都必须找到一些疯狂的工作,这样GUI才能保持完好无损。

很显然,我必须在单独的线程中检查来自服务器的命令,并在EDT中运行GUI组件。我的第二个实现有两个类 - 一个用于GUI,另一个用于Player。当时的想法是,该Player有这样举行的GUI,这样我可以从Player类访问GUI的变量,像这样:

class Player 
{ 
    public GUI gui; 

    ... 

    // And then start this gui inside of the EDT. 
    EventQueue.invokeLater(new Runnable() 
    { 
     public void run() 
     { 
       this.gui = new GUI().setVisible(true); 
     } 
    } 

这也不管用,新Runnablethis因为里面对象是指Runnable对象,而不是Player

如何在一个线程中的Player类与EDT线程中相应的GUI类之间进行通信?

回答

0

而不是使用匿名内部类,为什么不只是声明一个类的实现Runnable,并有一个构造函数将GUI实例作为参数?

此外,如果您的GUI类不是线程安全的,请考虑使用消息队列在EDT &主线程之间进行通信。

3

来处理与this指针你的问题,你应该写:

class Player 
{ 
    public GUI gui; 

    ... 

    // And then start this gui inside of the EDT. 
    EventQueue.invokeLater(new Runnable() 
    { 
     public void run() 
     { 
       Playser.this.gui = new GUI().setVisible(true); 
     } 
    } 
} 
1

你可以试试这个:

类球员 { public GUI gui;

... 

// And then start this gui inside of the EDT. 
EventQueue.invokeLater(new Runnable() 
{ 
    public void run() 
    { 
      Player.this.gui = new GUI().setVisible(true); 
    } 
} 
2

鲍里斯·帕夫洛维奇得到语法正确的(实际上,你可以只取出this.),但仍是代码没有意义。 字段在Runnable事件排队后的某个时间被初始化,所以播放器线程使用它是不安全的。

您可以在EDT上构建Player(但在EDT上执行网络操作)。或者将GUI注册为Player的监听器(观察者)。 invokeAndWait可以工作,但是很危险,因为它经常导致偶尔难以调试的死锁。

1

“直到我意识到整个玩家类在EDT现在正执行”

发生在美国东部时间,但要求这个类可能不是方法的构造函数。

您应该按照最初的设计构建播放器GUI。

EventQueue.invokeLater(new Runnable() 
{ 
    public void run() 
    { 
     new Player().setVisible(true); 
    } 
}); 

但玩家可以在构造函数中启动一个单独的线程(我个人会在玩家之间共享一个连接)。

当然,修改可见组件时,服务器的回调方法应该使用invokeLater()。