【问题标题】:IO thread alert GUI thread if error occures如果发生错误,IO 线程警报 GUI 线程
【发布时间】:2010-08-19 20:11:33
【问题描述】:

我有一个客户端/服务器问题,我正在尝试找出最佳解决方案。

如果客户端因任何原因与服务器断开连接,我希望输入输出线程有一种方法可以提醒 gui 线程出现问题,从而让 gui 线程打印错误并优雅地处理它(可能会退出登录 gui)。创建初始 gui 线程后,客户端可以更改为任意数量的 gui,这取决于他在做什么,所以我想我需要一种方法来动态查看当前正在运行的 gui。

到目前为止,我正在考虑这样做的方式:

1) 创建一个创建并显示每个 gui 的对象。因此,与其调用 invokeLater...SomeGui.CreateAndShoGui()...,不如让这个对象负责执行此操作,即 GuiObject.showSomeGui();

2) 让每个 gui 实现一个接口,这将确保有一个方法,当我们失去与服务器的连接时,该方法会在调用时正常关闭此 gui。

3) 有一个线程来监控 IO 线程和 gui 对象。如果 IO 线程出现问题,IO 线程将关闭并通知监控线程我们与服务器断开连接。然后,监控线程可以提醒任何打开的 gui(来自 gui 对象)我们已失去连接并且需要关闭。

我刚刚开始考虑这个问题,到目前为止,这是我想出的最佳解决方案。这似乎是一个不会给代码增加太多复杂性的合理解决方案吗?或者任何人都可以推荐一个更容易让人们阅读代码理解的解决方案?

谢谢

编辑: 我正在玩弄的另一个选项是在 IO 线程上有一个对象,该对象在打开时也会传递给每个新的 gui。该对象会将当前打开的 gui 引​​用返回给 io 线程,以便 io 线程可以在出现问题时提醒它。不过我反对这个解决方案,因为如果你有一个专门用于让它工作的对象(如上面的解决方案),而不是将一些晦涩的对象传递给每个 gui,它似乎会更容易阅读。

【问题讨论】:

    标签: java multithreading user-interface client-server notifications


    【解决方案1】:

    让我来看看你的每一个想法:

    1) 坏主意 - 您通过单个对象将整个应用程序捆绑在一起。这使得可维护性变得困难,并且是模块化的对立面。

    2) 恕我直言,这是要走的路。由于似乎每个 gui 在失败情况下都有独特的逻辑,因此可以推断出最能理解要做什么的对象就是 gui 对象本身。

    这个想法的另一个版本是为每个 gui 创建一个适配器,以将这个失败逻辑放入其中。这样做的好处是你的应用程序框架和你的 gui 之间的依赖减少了。缺点是这是一个额外的复杂层。如果您的 gui 已经与您的应用程序非常耦合,那么我会选择接口方法。如果您想在另一个应用程序中重用您的 gui,那么适配器方式可以帮助实现这一点。

    3) 这很好地补充了#2。所以让我直截了当地说 - 你将有 3 个线程:IO 线程、监视器线程和 UI 线程。我不知道你是否需要监控线程。从您所说的来看,IO 线程将能够自行检测到连接问题(可能是因为捕获了某种形式的 IOException)。当发现连接问题时,IO 线程并不忙,因为它很快就会自行关闭,所以它可能只负责通知 gui 有问题。无论如何,gui 应该在 UI 线程上调用其接口方法,因此 IO 线程只是调用一堆 invokeLater() 调用(或 SWT 的 asyncExec() 调用),然后 IO 线程可以自行关闭。

    4)(您的编辑)您基本上是在描述访问者模式。我认为这不是一个好的解决方案,因为调用是从 IO 线程到 gui 而不是相反。我不确定在这种情况下传递访问者对象会有什么帮助。

    最后一个想法。如果您使您的界面通用(不是特定于 gui),那么您可以将此模式应用于其他资源。例如,您可能希望在失去连接时刷新您的用户凭据(因为您谈到要再次进入登录屏幕)。这不是真正的 gui 逻辑,不应该在 gui 类中完成。

    编辑:我会使用事件模型。假设您创建了一个这样的界面:

    public interface ConnectionFailureListener {
        void handleConnectionFailure(); // Add an event object if you need it
    }
    

    然后您可以在某个对象中注册方法(可能是 IO 线程的 Runnable 或其他方便您的地方)。这些方法非常标准:

    public void addConnectionFailureListener(ConnectionFailureListener l) {}
    public void removeConnectionFailureListener(ConnectionFailureListener l) {}
    

    当您在屏幕上显示 gui 时,您会将其添加到您的注册对象中,当您关闭 gui 时,您会将其从注册对象中删除。您可以根据需要添加其他类型的对象 - 例如,当您登录时,您可以为您的凭据系统添加一个侦听器,并在处理注销时再次将其删除。

    这样,当您遇到故障情况时,您只需遍历当前注册的侦听器,侦听器就会执行它的操作。

    【讨论】:

    • 我的下一个问题是,如果每个 gui 都实现了一个接口,那么 IO 线程如何知道在什么上调用 closeGui 方法?可以启动任意数量的不同 gui,如果我没记错的话,IO 线程必须引用当前的 gui 才能调用该方法?还是我在这里遗漏了什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-03
    • 2012-08-06
    • 2011-09-14
    • 2018-12-14
    • 1970-01-01
    相关资源
    最近更新 更多