EDT 和主线程之间的通信

发布于 2024-07-18 05:31:26 字数 1216 浏览 5 评论 0原文

我一直在问很多关于我最近正在进行的项目的问题。 这是我所处的场景,任何帮助或指出正确的方向都会有很大帮助......

这是一个用服务器和多个客户端构建的网络程序。 每个客户端都有一个 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

谢绝鈎搭 2024-07-25 05:31:26

要处理 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);
         }
    }
}

To handle your problem with the this pointer, you should write:

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);
         }
    }
}
会傲 2024-07-25 05:31:26

你可以尝试这个:

class Player
{
公共GUI;

...

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

You may try this:

class Player
{
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);
     }
}
简单爱 2024-07-25 05:31:26

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. The gui field is initialised sometime after the Runnable 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 the Player. invokeAndWait would work, but is dangerous as it often leads to the occasional difficult-to-debug deadlock.

冷弦 2024-07-25 05:31:26

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

构造函数发生在 EDT 上,但在此类上调用的方法可能不会发生。

您应该按照您最初的意图构建播放器 GUI。

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

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

当然,在修改可见组件时,来自服务器的回调方法应该使用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.

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

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.

烟─花易冷 2024-07-25 05:31:26

为什么不直接声明一个实现 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文