如何将协程直接分派到 JVM 上的主线程?
How to dispatch coroutines directly to main thread on the JVM?
我正在为 jvm 设置一个基于 kotlin 协程的网络框架。客户端和服务器 类 实现了 CoroutineScope,并且 coroutinecontext 的覆盖是 Dispatchers.IO,因为我很确定这是用于这种情况的正确 Dispatcher。但是,我希望在主线程上处理读取数据包,或者至少提供该选项。在没有阅读文档的情况下,我使用了 Dispatchers.Main,我现在意识到它是用于 android UI 线程的。有没有我可以用来在主线程上获取协程 运行 的调度程序?如果没有,我将如何着手制作一个?
我查看了有关如何基于单个线程创建调度程序的 kotlin 文档,但除了创建新线程的 newSingleThreadContext 之外我找不到任何内容。我还发现可以从 java Executor 创建一个调度程序,但我仍然不确定如何将其限制为已经存在的线程。
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)
}
}
}
因此,由于缺少 android 组件,Dispatchers.Main 我得到一个 IllegalStateException。有没有办法创建一个阻塞主线程直到它完成的调度程序(就像 runBlocking 一样?)谢谢!
根据 Guide to UI programming with coroutines kotlinx.coroutines 有三个模块为不同的 UI 应用程序库提供协程上下文:
- kotlinx-coroutines-android -- Dispatchers.Main Android 的上下文
应用程序。
- kotlinx-coroutines-javafx -- Dispatchers.JavaFx JavaFX 上下文 UI
应用程序。
- kotlinx-coroutines-swing -- Dispatchers.Swing Swing 上下文 UI
应用程序。
此外,UI 调度程序可通过 Dispatchers.Main
来自 kotlinx-coroutines-core 和相应的实现(Android、JavaFx 或 Swing ) 由 ServiceLoader API 发现。例如,如果您正在编写 JavaFx 应用程序,则可以使用 Dispatchers.Main
或 Dispachers.JavaFx
扩展名,它们将是相同的对象。
runBlocking
正是您所需要的。它创建一个调度程序并将其设置在协程上下文中。您可以使用
访问调度程序
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
我正在为 jvm 设置一个基于 kotlin 协程的网络框架。客户端和服务器 类 实现了 CoroutineScope,并且 coroutinecontext 的覆盖是 Dispatchers.IO,因为我很确定这是用于这种情况的正确 Dispatcher。但是,我希望在主线程上处理读取数据包,或者至少提供该选项。在没有阅读文档的情况下,我使用了 Dispatchers.Main,我现在意识到它是用于 android UI 线程的。有没有我可以用来在主线程上获取协程 运行 的调度程序?如果没有,我将如何着手制作一个?
我查看了有关如何基于单个线程创建调度程序的 kotlin 文档,但除了创建新线程的 newSingleThreadContext 之外我找不到任何内容。我还发现可以从 java Executor 创建一个调度程序,但我仍然不确定如何将其限制为已经存在的线程。
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)
}
}
}
因此,由于缺少 android 组件,Dispatchers.Main 我得到一个 IllegalStateException。有没有办法创建一个阻塞主线程直到它完成的调度程序(就像 runBlocking 一样?)谢谢!
根据 Guide to UI programming with coroutines kotlinx.coroutines 有三个模块为不同的 UI 应用程序库提供协程上下文:
- kotlinx-coroutines-android -- Dispatchers.Main Android 的上下文 应用程序。
- kotlinx-coroutines-javafx -- Dispatchers.JavaFx JavaFX 上下文 UI 应用程序。
- kotlinx-coroutines-swing -- Dispatchers.Swing Swing 上下文 UI 应用程序。
此外,UI 调度程序可通过 Dispatchers.Main
来自 kotlinx-coroutines-core 和相应的实现(Android、JavaFx 或 Swing ) 由 ServiceLoader API 发现。例如,如果您正在编写 JavaFx 应用程序,则可以使用 Dispatchers.Main
或 Dispachers.JavaFx
扩展名,它们将是相同的对象。
runBlocking
正是您所需要的。它创建一个调度程序并将其设置在协程上下文中。您可以使用
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