JavaFx2或ScalaFx+;阿克卡

JavaFx2或ScalaFx+;阿克卡,scala,javafx,javafx-2,akka,scalafx,Scala,Javafx,Javafx 2,Akka,Scalafx,如何在JavaFX/ScalaFX应用程序中运行Akka actors (这是基于第一个答案的问题更新) 解决方案是否共享相同的执行上下文?意思是让参与者调度器基于JavaFXExecutorService?(用于运行UI操作代码的代码) 这是否意味着一个代理将代表UI并能够操纵它?我的意思是,因为下面建议,如果两个参与者在UI ExecutorService上,这不意味着在代理之间共享一个状态(对象就是UI)吗 两个参与者在使用不同的executor服务时是否可以通信?我这样问是因为根据下面的

如何在JavaFX/ScalaFX应用程序中运行Akka actors

(这是基于第一个答案的问题更新)

解决方案是否共享相同的执行上下文?意思是让参与者调度器基于JavaFXExecutorService?(用于运行UI操作代码的代码)

这是否意味着一个代理将代表UI并能够操纵它?我的意思是,因为下面建议,如果两个参与者在UI ExecutorService上,这不意味着在代理之间共享一个状态(对象就是UI)吗

两个参与者在使用不同的executor服务时是否可以通信?我这样问是因为根据下面的建议,一些代理将在UI Executor服务上,而另一些则不在


最后,为什么按原样使用akka(其on Executor上下文不同)并使用Platform.runLater,可能会对UI的性能产生一些影响。我在同一个应用程序中提出了多个执行器服务的问题:这是坏的吗?< /P> < P>在JavaFX中使用多个线程时需要考虑的两个问题:

  • 任何最终接触到场景图的代码(例如,通过更新绑定到控件的数据)都必须包装在
    Platform.runLater
    中。如果您在JavaFX中使用内置多线程API(即
    任务
    服务
    ),这将自动完成,但如果您使用任何其他多线程实用程序,则必须自己完成

  • 您的多线程实用程序(即Akka)必须(我认为)以某种方式被告知为JavaFX事件线程留出一些空间。如果您查看源代码,您会发现他们在配置执行器时非常小心。我不确定这方面的细节,但当我尝试使用Scala的
    Future
    s和JavaFX时,我发现在使用默认的
    ExecutionContext
    时,UI中出现了一些无响应的情况,当我使用基于
    服务
    实现的自定义上下文时,这种情况消失了

ScalaFX(或据我所知的任何其他工具包)都不支持使用Scala Futures或Akka,让您忘记以上两点,但这肯定会很有趣。

  • 未来
将scala Futures与单线程工具包(如JavaFX)结合使用的最佳方法是定义一个执行器,该执行器允许您在UI工具包的线程上执行Futures或actors

Swing也存在同样的问题,这也需要对Swing线程进行更新。Viktor Klang提出了以下解决方案。这里是对JavaFX的翻译:

import akka.dispatch.ExecutionContext
import javafx.application.Platform
import java.util.concurrent.Executor

//
object JavaFXExecutionContext {
  implicit val javaFxExecutionContext: ExecutionContext = ExecutionContext.fromExecutor(new Executor {
  def execute(command: Runnable): Unit = Platform.runLater(command)
  })
}
您可以这样使用它:

// import the default ec
import scala.concurrent.ExecutionContext.Implicits.global
// define the JavaFX ec so we can use it explicitly
val fxec = JavaFXExecutionContext.javaFxExecutionContext
future {
  // some asynchronous computation, running on the default
  // ForkJoin ExecutionContext because no ec is passed
  // explicitly
}.map(result => {
  // update JavaFX components from result
  // This will run in the JavaFX thread.
  // Check Platform.isFxApplicationThread() to be sure!
})(fxec)
只要与JavaFX组件交互的步骤都在JavaFXExecutionContext上运行,未来的管道就可能非常复杂

注意:是否将ForkJoin ec设置为默认值并显式传递JavaFX ec取决于您自己,反之亦然。将javafxec设置为默认值可能是一个好主意,以防止出现错误,并标记可以使用ForkJoin ec显式异步运行的部分

  • 演员
对于将基于参与者的系统与单线程UI工具包集成,还有一个解决方案。看见你所要做的就是换新的

SwingUtilities.invokeLater(command)

你可以走了

  • 什么时候用哪个
如果您有一个大型UI应用程序,并且只想派生一些异步操作(加载文件或进行一些计算),那么基于未来的方法可能更可取。但是要小心不要与将来在默认执行上下文上异步运行的JavaFX组件进行任何交互(既不读也不写)


如果您有一个大型的基于actor的系统,并且只想将UI附加到某些部分,那么在JavaFX线程上运行几个actor可能是更好的选择。YMMV.

是关于akka演员的要点,可以在Swing或JavaFX线程上运行。这是Victor Klang基于的一个方便、可复制的扩展。

是的,这是可能的。我已经使用Scala、Akka和ScalaFX编写了三到四个应用程序供内部使用。编写JavaFX/ScalaFX多线程应用程序与编写任何其他多线程应用程序没有太大区别。您是否有任何具体问题导致您首先提出此问题?我这样问是因为在目前的表格中,您的问题IMO不适合Stackoverflow。如果您对使用scala、akka和scalafx的示例应用程序感兴趣,您可以查看。这是我为测试scala、akka和scalafx而创建的一个简单的俄罗斯方块游戏。两个演员可以在不同的executor服务上交流吗?是的,看这张照片。它在同一执行上下文上生成模型参与者,在JavaFx执行上下文上生成视图参与者。他们都可以互相交流。谢谢你的详细解释。我不确定是否完全理解演员的解决方案。你能解释一下让AKKA参与者的executionContext不同于JAVAFX的根本问题是什么吗?或者我说是遗嘱执行人?建议解决方案的主要目标是什么?什么时候您需要在与JavaFXUI线程相同的executorService上使用actor?如果您运行配置了默认执行上下文的actor,它将在线程池线程上执行。但是,不允许从任意线程修改甚至访问JavaFXGUI组件的状态,这将导致未定义的行为。因此,诀窍是配置所有以某种方式与GUI交互的参与者,以便使用JavaFXExecutionContext在GUI线程上执行。这样,您就拥有了一个行为与任何其他行为类似的行为(您可以安全地传递其ActorRef),但可以从其receive方法内部安全地访问GUI状态。是否可以从代理内部使用Platform.runlater更新
Platform.runLater(command)