java 使用 JavaFX Platform.runLater 并从不同线程访问 UI

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15160410/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 18:40:54  来源:igfitidea点击:

Usage of JavaFX Platform.runLater and access to UI from a different thread

javamultithreadingjavafx-2event-dispatch-thread

提问by swaechter

I have a few questions about Platform.runLater. I have a JavaFX Application class. In this class I run a thread (The thread reads data from a network socket).

我有几个关于Platform.runLater. 我有一个 JavaFX 应用程序类。在这个类中,我运行一个线程(该线程从网络套接字读取数据)。

Now when I create a new Stageinside the thread, the system throws an execption (JavaFX event dispatcher thread and my netork-read thread are not the same) - I understand this behaviour.

现在,当我Stage在线程中创建一个新线程时,系统会抛出一个 execption(JavaFX 事件调度程序线程和我的 netork-read 线程不一样)——我理解这种行为。

But the other side is, I append the text from the network-reader to an existing TextAreaor add/remove some items in a ListView<String>- this doesn't throw an exception - why ? I thought JavaFX is singlethreaded (The ui library part). Is this the same thing as in Swing: Sometimes it works and sometimes you have just garbage (Because EDT)?

但另一方面,我将来自网络阅读器的文本附加到现有的TextArea或添加/删除一些项目ListView<String>- 这不会引发异常 - 为什么?我认为 JavaFX 是单线程的(ui 库部分)。这是否与 Swing 中的相同:有时它有效,有时您只有垃圾(因为 EDT)?

My questions:

我的问题:

  • When does the JavaFX event dispatcher thread throw an exception and when not ?
  • Are the any good documents about this
  • Is there an easier (shorter & cleaner) way to use Platform.runLaterwith a run()method ? In combination with a try catch (or multiple catch), it looks very strange
  • JavaFX 事件调度程序线程何时抛出异常,何时不抛出?
  • 有没有关于这个的好文件
  • 是否有更简单(短和清洁剂)的方式来使用Platform.runLater同一个run()方法?结合一个try catch(或者multiple catch),看起来很奇怪

I know the usage of Platform.runLaterin a thread isn't that nice (design solution)

我知道Platform.runLater在线程中的使用不是那么好(设计解决方案)

回答by jewelsea

Alexander's answer catches the most important points regarding your questions.

亚历山大的回答抓住了关于你的问题的最重要的观点。

This answer provides some supplemental information.

这个答案提供了一些补充信息。

When does the JavaFX event dispatcher thread throw an exception and when not ?

JavaFX 事件调度程序线程何时抛出异常,何时不抛出?

The JavaFX system does not always check that accesses to objects affecting the active scene graph are properly restricted to the JavaFX thread. Ultimately, ensuring such thread safety is the responsibility of the JavaFX application programmer - not the JavaFX system. You must be very careful when performing multi-threaded programming in JavaFX, otherwise application behaviour may fail or become unpredictable.

JavaFX 系统并不总是检查对影响活动场景图的对象的访问是否正确地限制在 JavaFX 线程中。最终,确保此类线程安全是 JavaFX 应用程序程序员的责任,而不是 JavaFX 系统。在 JavaFX 中执行多线程编程时必须非常小心,否则应用程序行为可能会失败或变得不可预测。

Are the any good documents about this

有没有关于这个的好文件

Try the the JavaFX tutorial: Concurrency in JavaFX.

试试 JavaFX 教程:JavaFX 中的并发

Is there an easier (shorter & cleaner) way to use Platform.runLater with a run() method?

有没有更简单(更短更干净)的方法来使用 Platform.runLater 和 run() 方法?

No. Platform.runLateris as simple as it gets.

Platform.runLater,就这么简单。



As an aside . . .

作为旁白 。. .

Task and Service

任务与服务

Consider using the Taskor Servicesubclasses of Worker. These are JavaFX wrappers for FutureTask(which is in turn a Runnable). Workers provide a callmethod to run logic on a background thread. They maintain execution status(with thread safe callback notification to the JavaFX thread for state changes) and return results of the call via value, messageand exceptionproperties.

考虑使用WorkerTaskService子类。这些是FutureTask 的JavaFX 包装器(它又是一个Runnable)。Worker 提供了一个调用方法来在后台线程上运行逻辑。它们维护执行状态(通过向 JavaFX 线程发送状态更改的线程安全回调通知)并通过valuemessageexception属性返回调用结果。

Take advantage of the design patterns in the Taskand Servicejavadoc examples to simplify creation of thread-safe applications with features such as:

利用TaskServicejavadoc 示例中的设计模式来简化具有以下功能的线程安全应用程序的创建:

  • Asynchronous fetching of data for UI update.
  • Periodic message updates for task progress.
  • Constructing Node graphs which are not yetattached to a displayed scene.
  • Monitoring progress via progress bars, etc.
  • 异步获取数据以进行 UI 更新。
  • 任务进度的定期消息更新。
  • 构建尚未附加到显示场景的节点图。
  • 通过进度条等监控进度。

A Workeris complementary to Platform.runLater. Use Platform.runLaterwhen you are executing off of the JavaFX Application Thread and you want to run some logic on the JavaFX application Thread. Use a Workerwhen you are running on the JavaFX Application Thread and want to spawn some logic or (especially) I/O on a new thread so that you don't block the JavaFX Application Thread. You would never want to do network I/O inside a Platform.runLater's runmethod, but would often want to do it in a Worker's callmethod.

AWorker是 的补充Platform.runLater。使用Platform.runLater时会提供的JavaFX应用程序线程的执行关闭,要运行的JavaFX应用程序线程一些逻辑。使用Worker时,您是在JavaFX应用程序线程运行,并希望产卵一些逻辑或(尤其是)I / O上一个新的线程,这样你就不会阻塞了JavaFX应用程序线程。您永远不会希望在 aPlatform.runLaterrun方法中进行网络 I/O ,但通常希望在 aWorkercall方法中进行。

Also, usage of Taskand Serviceis not incompatible with use of Platform.runLater. For instance, if you have a very long running Taskfrom which you want to return partial results to the UI periodically or as a buffer fills, then executing Platform.runLaterin the task's callmethod is the way to do that.

此外,Task和 的Service使用与 的使用并非不兼容Platform.runLater。例如,如果您有一个很长的运行Task时间,您希望定期或在缓冲区填充时将部分结果返回到 UI,那么Platform.runLater在任务的call方法中执行就是这样做的方法。

Workers are useful when you don't have an existing threaded service provided by a library, but are instead creating your own threads to execute in the background. If you have an existing threaded service, then you will need to use Platform.runLaterto perform logic on the JavaFX application thread.

当您没有库提供的现有线程服务,而是创建自己的线程以在后台执行时,Worker 会很有用。如果您有一个现有的线程服务,那么您将需要使用Platform.runLaterJavaFX 应用程序线程来执行逻辑。

Note that you still need to know what you are doing, even if you use a Worker. You must still take care that you don't violate standard JavaFX concurrency rules, such as never updating Nodes on the active scene graph (including not updating values that Nodes in the active scene graph are bound to - such as the observable list of itemsbacking a ListView).

请注意,即使您使用Worker. 您仍然必须注意不要违反标准的 JavaFX 并发规则,例如永远不要更新活动场景图中的节点(包括不更新活动场景图中的节点绑定到的值 - 例如支持的可观察项目列表)一个列表视图)。

回答by Alexander Kirov

"this doesn't throw an exception - why?" because not all such cases are cought... Possibly, because of performance considerations, possibly, it is just a missed functionality.

“这不会抛出异常——为什么?” 因为并非所有此类情况都被排除在外……可能,出于性能方面的考虑,可能只是错过了一个功能。

All interactions with JavaFX objects (including creation) must be done on JFX thread, if you want to access those JFX objects from another thread - use runLater or runAndWait methods. If it doesn't throw exception now, it possibly will start to throw exceptions in the future. Any interaction with JFX object may cause a subsequent actions and event, which will be cought by some thread checker - you cannot be sure.

与 JavaFX 对象的所有交互(包括创建)都必须在 JFX 线程上完成,如果您想从另一个线程访问这些 JFX 对象 - 使用 runLater 或 runAndWait 方法。如果它现在不抛出异常,它将来可能会开始抛出异常。与 JFX 对象的任何交互都可能导致后续操作和事件,这些操作和事件将被某些线程检查器排除 - 您无法确定。

I don't think, there is any good documentation on this - just a simple rule - use runLater or runAndWait.

我不认为,对此有任何好的文档 - 只是一个简单的规则 - 使用 runLater 或 runAndWait。

Shorter and cleaner way - will be provided in JDK 8 using Lambda.

更短更简洁的方式 - 将在 JDK 8 中使用 Lambda 提供。