EDT 和主线程之间的通信
我一直在问很多关于我最近正在进行的项目的问题。 这是我所处的场景,任何帮助或指出正确的方向都会有很大帮助......
这是一个用服务器和多个客户端构建的网络程序。 每个客户端都有一个 GUI,它必须根据服务器发送的命令进行操作。 每个客户端都包装在一个名为 Player
的类中。 这个Player
有一个GUI(扩展JFrame
)和一个main方法,而服务器只有一个main方法(没有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);
}
}
这也不起作用,因为新的 Runnable 对象中的 this 引用的是 Runnable 对象,而不是 Player。
如何在一个线程中的 Player
类与 EDT 线程中相应的 GUI 类之间进行通信?
I have been asking a lot of questions about a project I have been working on recently. Here is the scenario I am in and any help or point in the right direction would help a lot...
This is a network program built with a server and multiple clients. Each client has a GUI which must act according to commands sent from the server. Each client is wrapped within a class called Player
. This Player
has a GUI (extends JFrame
) and a main method, and the Server has a main method only (no GUI). At first, this class was created in the main thread like this:
EventQueue.invokeLater(new Runnable()
{
public void run()
{
new Player().setVisible(true);
}
});
This was working fine, until I realized that the entire Player
class was now executing in the EDT. So, when I wait for commands from the server the entire GUI locks up until that command is sent and proper actions are executed. As you can imagine, this is a horrible design and proved to be a real pain of a coding environment when every time you want to check for something you must find some crazy work around so that the GUI still remains intact.
Obviously, I must check for the commands from the Server in a separate thread and run the GUI components in the EDT. My second implementation had two classes - one for the GUI and one for the Player
. The idea was that the Player
had a variable that held the GUI so that I could access the GUI from the Player
class, something like this:
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);
}
}
This doesn't work either, because this
inside of the new Runnable
object refers to the Runnable
object, not the Player
.
How can I communicate between the Player
class in one thread and the corresponding GUI class in the EDT thread?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
要处理
this
指针的问题,您应该编写:To handle your problem with the
this
pointer, you should write:你可以尝试这个:
class Player
{
公共GUI;
You may try this:
class Player
{
public GUI gui;
Boris Pavlović 的语法是正确的(实际上你可以删除
this.
),但代码仍然没有意义。gui
字段在Runnable
事件排队后的某个时间初始化,因此播放器线程使用它是不安全的。您可以在 EDT 上构造
Player
(但在 EDT 之外执行网络操作)。 或者将 GUI 注册为Player
的侦听器(观察者)。invokeAndWait
可以工作,但很危险,因为它经常会导致偶尔难以调试的死锁。Boris Pavlović gets the syntax right (actually you could just remove the
this.
), but still the code doesn't make sense. Thegui
field is initialised sometime after theRunnable
event is queued, so it is unsafe for the player thread to use it.You could construct
Player
on the EDT (but do the network operations off EDT). Or register the GUI as a listener (observer) of thePlayer
.invokeAndWait
would work, but is dangerous as it often leads to the occasional difficult-to-debug deadlock.“直到我意识到整个 Player 类现在正在 EDT 中执行”
构造函数发生在 EDT 上,但在此类上调用的方法可能不会发生。
您应该按照您最初的意图构建播放器 GUI。
但玩家可以在构造函数中启动一个单独的线程(我个人会在玩家之间共享一个连接)。
当然,在修改可见组件时,来自服务器的回调方法应该使用invokeLater()。
"until I realized that the entire Player class was now executing in the EDT"
The constructor occurs on the EDT but methods called on this class might not be.
You should construct the player GUI as you originally intended.
But Player can launch a separate thread in the constructor (personally I'd share a connection between the Players).
Of course, the callback methods from the server should use invokeLater() when modifying visible components.
为什么不直接声明一个实现 Runnable 的类并使用一个以 GUI 实例作为参数的构造函数,而不是使用匿名内部类呢?
另外,如果您的 GUI 类不是线程安全的,请考虑使用消息队列在 EDT 和 GUI 之间进行通信。 主线程。
Instead of using an anonymous inner class, why not just declare a class the implements Runnable and have a constructor that takes a GUI instance as argument?
Also, if your GUI class is not thread safe, consider using a message queue to communicate between the EDT & main thread.