【问题标题】:Interacting with UI threads in Java/J2ME在 Java/J2ME 中与 UI 线程交互
【发布时间】:2008-11-15 14:09:36
【问题描述】:

我正在编写一个 J2ME 应用程序。其中之一是定期轮询目录的内容,如果有任何新内容,则将它们绘制在屏幕上。我通过让 UI 表单启动一个带有指向自身的指针的轮询线程来完成此操作,并且当轮询线程找到某些内容时,它会回调表单并调用同步方法来更新它的显示。这似乎工作正常。

我的问题是这样的。在 C#/.NET 中,我知道让非 UI 线程更新 UI 并不好,处理此问题的正确方法是将其委托给 UI 线程。

例如以下:

public void DoSomeUIThing()
{
    if (this.uiComponent.InvokeRequired)
    {
        this.uiComponent.Invoke(someDelegateThatCallsBackToThis);
    }
    else
    {
        this.uiComponent.Text = "This is the update I want to happen";
    }
}

是否有一个 J2ME 等价物来管理这个过程? Java怎么样?还是 Java/J2ME 在这方面做得更好?如果没有,这是怎么做到的?

[编辑] Swing 似乎支持我通过 SwingUtilities.invokeLater() 和 invokeAndWait() 方法提出的问题。是否有 J2ME 的等效框架?

【问题讨论】:

  • 刚刚用 J2ME 特定信息完成了我的回答
  • 谢谢!我的应用是 LCDUI,所以我想我不必担心这个(至少如果我相信 David Pierce)。

标签: c# java multithreading java-me ui-thread


【解决方案1】:

关于 Java,您所描述的内容类似于 SwingWorker (worker thread)

当 Swing 程序需要执行长时间运行的任务时,它通常会使用其中一个工作线程,也称为后台线程。

Swing 程序包括以下几种线程:

  • 初始线程,执行初始应用程序代码的线程。
  • 事件调度线程,所有事件处理代码都在其中执行。大多数与 Swing 框架交互的代码也必须在这个线程上执行。
  • 工作线程,也称为后台线程,执行耗时的后台任务。

Single-thread rule:
一旦实现了一个 Swing 组件,所有可能影响或依赖于该组件状态的代码都应该在事件调度线程中执行。

在 J2EE 上下文中使用时,referencing a SwingWorker from an EJB 时需要小心。

关于 J2ME,这取决于您是将应用程序开发为可在任何支持 MIDP 的设备上运行的标准 MIDlet,还是例如作为 RIMlet ,一个基于 CLDC 的应用程序,它使用 BlackBerry 特定的 API,因此只能在 BlackBerry 设备上运行。

因为与 MIDP 的 UI 类不同,RIM 类似于 Swing,因为 UI 操作发生在事件线程上,这不像 MIDP 中那样是线程安全的。要在事件线程上运行代码,应用程序必须获得事件对象上的锁,或者使用 invokeLater() 或 invokeAndWait()——这对开发人员来说是额外的工作,但复杂性是有代价的。

但是对于LCDUI,你可以access a form from multiple threads

【讨论】:

  • 查看编辑 - “单线程规则”链接描述了如何为摇摆执行此操作。你知道 J2ME 中类似的东西吗?
【解决方案2】:

Java ME 有很多配置文件。如果您的意思是 MIDP,那么 Display.runSerially 就是您想要的。

对于 AWT (Swing),您将使用 EventQueue.invokeLaterSwingUtilities.invokeLater 仅由于 Java 1.1 没有 EventQueue 方法而需要 - 1.2 即将庆祝其十岁生日)。对于通用 DOM API,请使用 DOMService.invokeLater

无论 GUI API 对线程安全提出什么声明,它们都可能是错误的(Swing 的一些声明在 JDK7 中被删除,因为它们不可实现)。在任何情况下,应用程序代码都不太可能是线程安全的。

【讨论】:

    【解决方案3】:

    对于 j2me 应用程序,您可能希望保持简单。主要是只在事件线程中触摸 UI 组件。这样做的直接方法是使用invokeLater or invokeAndWait。根据您的图书馆,您将无法访问除此之外的任何内容。通常,如果您的平台中未提供这些,则可能等同于没有线程支持并且不是问题。例如the blackberry does support it

    【讨论】:

      【解决方案4】:

      如果你在 SWT 下开发,这是通过 Display 对象的 asyncExec() 方法完成的。您传递一个实现 Runnable 的对象,以便 UI 线程执行在其他线程中完成的更改。

      这是从here借来的例子

      public void itemRemoved(final ModelEvent me)
      {
         final TableViewer tableViewer = this.viewer;
      
         if (tableViewer != null)
         {
            display.asyncExec(new Runnable()
            {
               public void run()
               {
                  tableViewer.remove(me.getItem());
               }
            }
         }
      }
      

      【讨论】:

        【解决方案5】:

        我可以证明 MIDP UI 工具包确实是线程安全的,因为我在几乎所有制造商生产的数百万部手机上运行具有复杂 GUI 的大型 MIDlet,我从未见过这方面的问题。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-04-18
          • 2010-12-16
          • 2015-01-04
          • 1970-01-01
          • 2023-02-24
          • 2011-11-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多