-
-
Save mucaho/8973013 to your computer and use it in GitHub Desktop.
package akka.dispatch.gui | |
// original work copyright 2012 Viktor Klang | |
/** | |
* (A). define the gui dispatchers programmaticaly | |
*/ | |
import akka.dispatch.{DispatcherPrerequisites, ExecutorServiceFactory, ExecutorServiceConfigurator} | |
import com.typesafe.config.Config | |
import java.util.concurrent.{ExecutorService, AbstractExecutorService, ThreadFactory, TimeUnit} | |
import java.util.Collections | |
import javax.swing.SwingUtilities | |
import javafx.application.Platform | |
// First we wrap invokeLater/runLater as an ExecutorService | |
abstract class GUIExecutorService extends AbstractExecutorService { | |
def execute(command: Runnable): Unit | |
def shutdown(): Unit = () | |
def shutdownNow() = Collections.emptyList[Runnable] | |
def isShutdown = false | |
def isTerminated = false | |
def awaitTermination(l: Long, timeUnit: TimeUnit) = true | |
} | |
object JavaFXExecutorService extends GUIExecutorService { | |
override def execute(command: Runnable) = Platform.runLater(command) | |
} | |
object SwingExecutorService extends GUIExecutorService { | |
override def execute(command: Runnable) = SwingUtilities.invokeLater(command) | |
} | |
// Then we create an ExecutorServiceConfigurator so that Akka can use our JavaFXExecutorService for the dispatchers | |
class JavaFXEventThreadExecutorServiceConfigurator(config: Config, prerequisites: DispatcherPrerequisites) extends ExecutorServiceConfigurator(config, prerequisites) { | |
private val f = new ExecutorServiceFactory { | |
def createExecutorService: ExecutorService = JavaFXExecutorService | |
} | |
def createExecutorServiceFactory(id: String, threadFactory: ThreadFactory): ExecutorServiceFactory = f | |
} | |
// Then we create an ExecutorServiceConfigurator so that Akka can use our SwingExecutorService for the dispatchers | |
class SwingEventThreadExecutorServiceConfigurator(config: Config, prerequisites: DispatcherPrerequisites) extends ExecutorServiceConfigurator(config, prerequisites) { | |
private val f = new ExecutorServiceFactory { | |
def createExecutorService: ExecutorService = SwingExecutorService | |
} | |
def createExecutorServiceFactory(id: String, threadFactory: ThreadFactory): ExecutorServiceFactory = f | |
} |
/** | |
* (B). Then we simply need to create a dispatcher configuration in our application.conf | |
*/ | |
javafx-dispatcher { | |
type = "Dispatcher" | |
executor = "akka.dispatch.gui.JavaFXEventThreadExecutorServiceConfigurator" | |
throughput = 1 | |
} | |
swing-dispatcher { | |
type = "Dispatcher" | |
executor = "akka.dispatch.gui.SwingEventThreadExecutorServiceConfigurator" | |
throughput = 1 | |
} |
// After that we just create the GUI Actors with a Props with the correct dispatcher set: | |
val javaFxActor = context.actorOf(Props[JavaFxActor].withDispatcher("javafx-dispatcher"), "javaFxActor") | |
val swingActor = context.actorOf(Props[SwingActor].withDispatcher("swing-dispatcher"), "swingActor") | |
// Done! Now all messages processed by the new actor will be executed by the Swing/JavaFX Event Dispatch Thread, enjoy! |
Hi there,
What do you mean by "Now all messages processed by the new actor will be executed by the Swing/JavaFX Event Dispatch Thread, enjoy!" Why would I want my actor action to be in the same thread context as the javaFx Thread?
@Maatary check the StackOverflow answer linking to this gist. Check the comments under that answer, I have added some explanatory comments there.
@OlekRia this is old, but the reason why this happens is because javafx blocks its own thread (after Platform.exit() or stage.close()) until it exits completely. So events that were dispatched to the dispatcher during system shutdown will never be processed.
So solution might look like this
primaryStage.setOnCloseRequest(e => {
e.consume()
implicit val ec = ExecutionContext.fromExecutorService(Executors.newSingleThreadExecutor())
system.whenTerminated.onComplete { _ =>
ec.shutdown()
Platform.exit()
}
system.terminate()
})
@haz00 Man... 9 years passed by. I already forgot Scala :) LOL. Seriously :)
You made my day :)))))))))
@OlekRia I just ran into this problem, so I'll leave the solution for the next generation :)
For archeologists :))))))))
Hi, thank you for notifying me. I will investigate.
A first idea though - Do you this at the end of your program?: