如何将协程直接分派到JVM上的主线程? [英] How to dispatch coroutines directly to main thread on the JVM?

查看:24
本文介绍了如何将协程直接分派到JVM上的主线程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为JVM设置一个基于Kotlin协程的网络框架。客户端和服务器类实现CoroutineScope,而coroutinecontext的重写是Dispatcher s.IO,因为我非常确定这是用于这种情况的正确调度程序。但是,我希望在主线程上处理读数据包,或者至少提供该选项。在没有阅读文档的情况下,我使用了Dispatcher s.Main,我现在意识到它是用于Android UI线程的。有没有调度器可以用来让协程在主线程上运行?如果没有,我该怎么做呢?

我查阅了Kotlin文档,了解如何创建基于单个线程的分派器,但除了创建新线程的newSingleThreadContext之外,我找不到其他任何东西。我还发现从Java执行器创建调度程序是可能的,但我仍然不确定如何将其限制在已经存在的线程上。

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。有没有办法创建一个Dispatcher来阻塞主线程直到它完成(就像runBlock所做的那样)?谢谢!

推荐答案

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

访问调度程序
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上的主线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆