DEV Community

Cover image for What is the Purpose of the Main Dispatcher?
João Esperancinha
João Esperancinha

Posted on • Edited on

What is the Purpose of the Main Dispatcher?

If you have this question, perhaps you are a long time server-side developer and are wondering what the Main Dispatcher is doing in the Kotlinx coroutines library? Well, the Main Dispatcher exists as kind of an interface, but its implementation isn't really there.

The Main dispatcher is used in Kotlin when programming something that will interact with some sort of UI. For the Dispatchers.Main scope to be available, one of these needs to be available: Android main thread dispatcher, JavaFx, or Swing EDT dispatcher. The Main dispatcher has one distinct characteristic that tells it apart from the others. This dispatcher is singe-threaded and it is not shipped with the kotlinx coroutines library.

Let’s look at one example:

class MainDispatcherLauncher {

    companion object {
        val logger: Logger = LoggerFactory.getLogger(MainDispatcherLauncher::class.java)

        @JvmStatic
        fun main(args: Array<String> = emptyArray()) = runBlocking {
            runMainCoroutinesTest()
        }

        private suspend fun runMainCoroutinesTest() {
            try {
                val job = CoroutineScope(Dispatchers.Main).launch {
                    launch {
                        delay(100)
                        logger.info("This is cat @ ${LocalDateTime.now()}")
                    }
                    launch {
                        logger.info("This is mouse @ ${LocalDateTime.now()}")
                    }
                    logger.info("This is master @ ${LocalDateTime.now()}")
                }
                job.join()
            } catch (ex: IllegalStateException) {
                logger.info("Error!", ex)
            }
        }

    }
}
Enter fullscreen mode Exit fullscreen mode

In this case, both launches would kickstart two coroutines and we would expect at least 3 log outputs in a normal situation. However, this will not work if simply running a standalone application or in a server-side setting. Since the Main disptacher isn’t available, running this code will result in:

Exception in thread "main" java.lang.IllegalStateException: Module with the Main dispatcher is missing. Add dependency providing the Main dispatcher, e.g. 'kotlinx-coroutines-android' and ensure it has the same version as 'kotlinx-coroutines-core'
    at kotlinx.coroutines.internal.MainDispatchersKt.throwMissingMainDispatcherException(MainDispatchers.kt:77)
    at kotlinx.coroutines.internal.MissingMainCoroutineDispatcher.missing(MainDispatchers.kt:108)
    at kotlinx.coroutines.internal.MissingMainCoroutineDispatcher.isDispatchNeeded(MainDispatchers.kt:92)
    at kotlinx.coroutines.test.internal.TestMainDispatcher.isDispatchNeeded(TestMainDispatcher.kt:31)
    at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:315)
    at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:26)
    at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable$default(Cancellable.kt:21)
    at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:88)
    at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:123)
    at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:52)
    at kotlinx.coroutines.BuildersKt.launch(Unknown Source)
    at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:43)
    at kotlinx.coroutines.BuildersKt.launch$default(Unknown Source)
    at org.jesperancinha.ktd.MainScopeLauncher$Companion.runMainCoroutinesTest(MainScopeLauncher.kt:20)
    at org.jesperancinha.ktd.MainScopeLauncher$Companion.access$runMainCoroutinesTest(MainScopeLauncher.kt:10)
    at org.jesperancinha.ktd.MainScopeLauncher$Companion$main$1.invokeSuspend(MainScopeLauncher.kt:15)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
    at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:277)
    at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:95)
    at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:69)
    at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
    at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:48)
    at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
    at org.jesperancinha.ktd.MainScopeLauncher$Companion.main(MainScopeLauncher.kt:14)
    at org.jesperancinha.ktd.MainScopeLauncher.main(MainScopeLauncher.kt)
    Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@2c039ac6, Dispatchers.Main]
06:44:49.864 [main] INFO org.jesperancinha.ktd.MainScopeLauncher -- Error!
java.lang.IllegalStateException: Module with the Main dispatcher is missing. Add dependency providing the Main dispatcher, e.g. 'kotlinx-coroutines-android' and ensure it has the same version as 'kotlinx-coroutines-core'
    at kotlinx.coroutines.internal.MainDispatchersKt.throwMissingMainDispatcherException(MainDispatchers.kt:77)
    at kotlinx.coroutines.internal.MissingMainCoroutineDispatcher.missing(MainDispatchers.kt:108)
    at kotlinx.coroutines.internal.MissingMainCoroutineDispatcher.isDispatchNeeded(MainDispatchers.kt:92)
    at kotlinx.coroutines.test.internal.TestMainDispatcher.isDispatchNeeded(TestMainDispatcher.kt:31)
    at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:315)
    at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:26)
    at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable$default(Cancellable.kt:21)
    at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:88)
    at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:123)
    at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:52)
    at kotlinx.coroutines.BuildersKt.launch(Unknown Source)
    at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:43)
    at kotlinx.coroutines.BuildersKt.launch$default(Unknown Source)
    at org.jesperancinha.ktd.MainScopeLauncher$Companion.runMainCoroutinesTest(MainScopeLauncher.kt:20)
    at org.jesperancinha.ktd.MainScopeLauncher$Companion.access$runMainCoroutinesTest(MainScopeLauncher.kt:10)
    at org.jesperancinha.ktd.MainScopeLauncher$Companion$main$1.invokeSuspend(MainScopeLauncher.kt:15)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
    at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:277)
    at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:95)
    at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:69)
    at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
    at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:48)
    at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
    at org.jesperancinha.ktd.MainScopeLauncher$Companion.main(MainScopeLauncher.kt:14)
    at org.jesperancinha.ktd.MainScopeLauncher.main(MainScopeLauncher.kt)
    Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: null

Process finished with exit code 0
Enter fullscreen mode Exit fullscreen mode

Remember to check the source for more details:

And if you have read this and have learned something new, you probably are ready to answer the following quiz:

The wonders of the Main Kotlin Coroutines Dispatcher JQ01 #jesprotech #softwarecreations #mainscope - YouTube

Imagine that this code is running in a simple Java executable application. Just a runnable with coroutines. What would you expect as a result with scope Main...

favicon youtube.com

And you can check your answer in the response video I created:

The Main Kotlin Coroutine Dispatcher (JA01) #jesprotech #softwarecreations #main #mainscope - YouTube

Hi there fine people!You can find the project that I've made exploring the different scopes and a lot more about Kotlin Coroutines here:- https://github.com/...

favicon youtube.com

Have a good one everyone!

Top comments (0)