5

我正在编写一个 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 是否有等效的框架?

4

5 回答 5

5

关于 Java,您所描述的看起来像SwingWorker (worker thread)

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

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

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

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

在 J2EE 上下文中使用时,从 EJB 引用 SwingWorker时需要小心。

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

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

但是对于LCDUI,您可以从多个线程访问一个表单

于 2008-11-15T14:26:31.790 回答
4

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

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

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

于 2008-11-15T17:54:25.630 回答
1

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

于 2008-11-15T15:04:26.907 回答
1

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

这是从这里借来的一个例子

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());
         }
      }
   }
}
于 2008-11-15T15:16:05.683 回答
1

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

于 2010-04-23T16:05:30.387 回答