与 Java/J2ME 中的 UI 线程交互
我正在编写一个 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 有等效的框架吗?
I'm writing a J2ME application. One of the pieces is something that polls the contents of a directory periodically, and, if there are any new things, paints them on the screen. I've done this by having the UI form launch a polling thread with a pointer back to itself, and when the polling thread finds something it calls back to the form and calls a syncrhonized method to update it's display. This seems to work fine.
The question I have is this. In C#/.NET I know it is not nice to have non-UI threads updating the UI, and the correct way to handle this is to delegate it up to the UI thread.
E.g. the following:
public void DoSomeUIThing()
{
if (this.uiComponent.InvokeRequired)
{
this.uiComponent.Invoke(someDelegateThatCallsBackToThis);
}
else
{
this.uiComponent.Text = "This is the update I want to happen";
}
}
Is there a J2ME equivalent for how to manage this process? How about Java? Or does Java/J2ME just play nicer in regard to this? If not, how is this done?
[EDIT] It appears that Swing supports what I'm asking about via the SwingUtilities.invokeLater() and invokeAndWait() methods. Is there an equivalent framework for J2ME?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
关于Java,您所描述的看起来像 SwingWorker (工作线程)。
当 Swing 程序需要执行长时间运行的任务时,它通常会使用其中一个工作线程,也称为后台线程。
Swing 程序包括以下类型的线程:
单线程规则:
一旦实现了 Swing 组件,所有可能影响或依赖于该组件状态的代码都应该在事件分派线程中执行。
在 J2EE 上下文中使用时,引用时需要小心来自 EJB 的 SwingWorker。
关于 J2ME,这取决于您是否将您的应用程序开发为可在任何支持 MIDP 的设备上运行的标准 MIDlet,或者例如开发为 RIMlet,这是一种基于 CLDC 的应用程序,使用 BlackBerry 特定的 API,因此只能在 BlackBerry 设备上运行。
因为与 MIDP 的 UI 类不同,RIM 与 Swing 类似,因为 UI 操作发生在事件线程上,而事件线程不像 MIDP 中那样是线程安全的。 要在事件线程上运行代码,应用程序必须获得事件对象的锁,或者使用invokeLater() 或invokeAndWait()——这对开发人员来说是额外的工作,但复杂性是有代价的。
但对于LCDUI,您可以从多个线程访问表单 。
Regarding Java, what you are describing looks like a SwingWorker (worker thread).
When a Swing program needs to execute a long-running task, it usually uses one of the worker threads, also known as the background threads.
A Swing program includes the following kinds of threads:
Single-thread rule:
Once a Swing component has been realized, all code that might affect or depend on the state of that component should be executed in the event-dispatching thread.
When used in a J2EE context, you need to be careful when you are referencing a SwingWorker from an EJB.
Regarding J2ME, it depends if you are developing your application as a standard MIDlet that will run on any MIDP-enabled device, or for instance as a RIMlet, a CLDC-based application that uses BlackBerry-specific APIs and therefore will run only on BlackBerry devices.
Because unlike MIDP's UI classes, RIM's are similar to Swing in the sense that UI operations occur on the event thread, which is not thread-safe as in MIDP. To run code on the event thread, an application must obtain a lock on the event object, or use invokeLater() or invokeAndWait() – extra work for the developer, but sophistication comes with a price tag.
But for LCDUI, you can access a form from multiple threads.
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 中被删除,因为它们不可实现)。 无论如何,应用程序代码不太可能是线程安全的。
There are many profiles of Java ME. If you mean MIDP then
Display.runSerially
is what you want.For AWT (Swing) you would use
EventQueue.invokeLater
(SwingUtilities.invokeLater
is only necessary due to Java 1.1 not having theEventQueue
method - 1.2 is about to celebrate its tenth birthday). For the Common DOM API, useDOMService.invokeLater
.No matter what claims a GUI API may make about thread-safety they are probably wrong (some of the claims of Swing are removed in JDK7 because they are not implementable). In any case, application code unlikely to be thread-safe.
对于 j2me 应用程序,您可能希望保持简单。 最重要的是仅在事件线程中触摸 UI 组件。 执行此操作的直接方法是使用 invokeLater或调用AndWait。 根据您的库,您将无法访问更多内容。 一般来说,如果您的平台中没有提供这些,则可能相当于没有线程支持并且不是问题。 例如,黑莓确实支持它。
For j2me apps you probably want to keep it simple. The main thing is to touch UI components only in the event thread. The direct way of doing this is to use invokeLater or invokeAndWait. Depending on your libraries you won't have access to anything more than that. In general if these aren't provided in your platform it probably equates to there being no thread support and not being an issue. For example the blackberry does support it.
如果您在 SWT 下进行开发,则可以通过 Display 对象的 asyncExec() 方法来完成。 您传递一个实现 Runnable 的对象,以便 UI 线程执行其他线程中所做的更改。
这是从此处借用的示例
If you develop under SWT this is accomplished by means of asyncExec() method of Display object. You pass an object implementing Runnable so the UI thread executes the changes done in other thread.
This is an example borrowed from here
我可以证明 MIDP UI 工具包确实是线程安全的,因为我有大型 MIDlet,具有复杂的 GUI,运行在几乎每个制造商生产的数百万部手机上,而且我从未见过这方面的问题。
I can attest that the MIDP UI toolkit is indeed thread-safe, as I have large MIDlets with complex GUI running on millions of phones made by almost every manufacturer, and I have never seen a problem in that regard.