提问者:小点点

如何在JVM上直接调度协程到主线程?


我正在为jvm设置一个基于kotlin协程的网络框架。客户端和服务器类实现了CoroutineScope,协程上下文的覆盖是Dispatchers.IO的,因为我很确定这是用于这种情况的正确Dispatcher。然而,我希望在主线程上处理读取数据包,或者至少提供该选项。没有读取留档,我使用了Dispatcher. Main,我现在意识到它是用于androidUI线程的。我可以使用调度程序在主线程上运行协程吗?如果没有,我将如何制作一个?

我在kotlin留档中查看了如何创建基于单个线程的调度程序,但是除了创建新线程的newSingleThreadContext之外,我找不到任何东西。我还发现可以从javaExecator创建调度程序,但是我仍然不确定如何将其限制在已经存在的线程中。

class AbstractNetworkComponent : CoroutineScope {
    private val packetProcessor = PacketProcessor()
    private val job = Job()
    override val coroutineContext = job + Dispatchers.IO
}

class PacketProcessor : CoroutineScope {

    private val job = Job()
    override val coroutineContext = job + Dispatchers.Main //Android only!
    private val packetHandlers = mutableMapOf<Opcode, PacketHandlerFunc>()

    fun handlePacket(opcode: Opcode, packet: ReceivablePacket, networker: Writable) {
        launch(coroutineContext) {
            packetHandlers[opcode]?.invoke(packet, networker)
        }
    }
}

因此,使用Dispatcher. Main,由于缺少android组件,我得到了一个IllegalStateException。有没有办法创建一个调度程序来阻塞主线程直到它完成(就像runBlock一样?)谢谢!


共2个答案

匿名用户

runBlock正是您所需要的。它创建一个调度程序并将其设置在协程上下文中。您可以使用

coroutineContext[ContinuationInterceptor] as CoroutineDispatcher

然后您可以将其传递给实现CoroutineScope的对象或您想用它做的任何其他事情。这是一些示例代码:

import kotlinx.coroutines.*
import kotlinx.coroutines.Dispatchers.IO
import kotlin.coroutines.ContinuationInterceptor

fun main() {
    println("Top-level: current thread is ${Thread.currentThread().name}")
    runBlocking {
        val dispatcher = coroutineContext[ContinuationInterceptor]
                as CoroutineDispatcher
        ScopedObject(dispatcher).launchMe().join()
    }
}

class ScopedObject(dispatcher: CoroutineDispatcher) : CoroutineScope {
    override val coroutineContext = Job() + dispatcher

    fun launchMe() = launch {
        val result = withContext(IO) {
            "amazing"
        }
        println("Launched coroutine: " +
                "current thread is ${Thread.currentThread().name}, " +
                "result is $result")
    }
}

这将打印

Top-level: current thread is main
Launched coroutine: current thread is main, result is amazing

匿名用户

根据协程UI编程指南,kotlinx. coroutines有三个模块为不同的UI应用程序库提供协程上下文:

  • kotlinx-coroutines-android--Dispatcher. Android应用程序的主要上下文。
  • kotlinx-coroutines-javafx--用于JavaFXUI应用程序的Dispatcher. JavaFx上下文。
  • kotlinx-coroutines-swing--用于SwingUI应用程序的Dispatcher. Swing上下文。

此外,UI调度程序可以通过kotlinx-coroutines-core的Dispatcher. Main获得,相应的实现(Android、JavaFx或Swing)由ServiceLoaderAPI发现。例如,如果您正在编写JavaFx应用程序,您可以使用Dispatcher.MainDispatcher.JavaFx扩展,它将是相同的对象。