如何将协程直接分派到 JVM 上的主线程?

2024-03-31

我正在为 jvm 设置一个基于 kotlin 协程的网络框架。 Client 和 Server 类实现 CoroutineScope,并且 coroutinecontext 的重写是 Dispatchers.IO,因为我非常确定这是用于这种情况的正确 Dispatcher。但是,我希望在主线程上处理读取数据包,或者至少提供该选项。在没有阅读文档的情况下,我使用了 Dispatchers.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)
        }
    }
}

因此,在 Dispatchers.Main 中,由于缺少 android 组件,我收到了 IllegalStateException 异常。有没有办法创建一个调度程序来阻塞主线程直到其完成(就像 runBlocking 那样?)谢谢!


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
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将协程直接分派到 JVM 上的主线程? 的相关文章

  • 调用许多网络服务的最佳方式?

    我有 30 家子公司 每家都实施了他们的 Web 服务 使用不同的技术 我需要实现一个Web服务来聚合它们 例如 所有子公司的Web服务都有一个名为的Web方法GetUserPoint int nationalCode 我需要实现我的网络服
  • 异步回调在哪个线程上运行?

    我正在做几个HttpWebRequest BeginGetResponse调用 并在回调方法中BeginGetResponse 我正在调用一个事件处理程序 在EventHandler中 有测试下载是否成功的逻辑 如果没有 它会尝试重新下载
  • 在不支持线程的程序加载的共享库中使用 C++11 多线程

    我目前正在尝试在共享库中使用 C 11 多线程 该库加载到 Linux 上的主程序 用 C 编写 中 这是一个大型模拟程序的一部分 我无法更改有关库加载的任何内容或更改一般的主程序 主程序是用 gcc 4 1 2 编译的 我没有它的源代码
  • VB - 以隐式方式链接 DLL

    我正在开发 VB6 图形界面 并且需要隐式链接到 DLL 这样做的动机来自于我上一个问题 https stackoverflow com questions 5194573 有问题的 DLL 使用静态 TLS declspec thread
  • 赋值运算符“=”是原子的吗?

    我正在使用全局变量实现线程间通信 global var volatile bool is true true thread 1 void thread 1 while 1 int rint rand 10 if is true cout l
  • 定期更新 SWT 会导致 GUI 冻结

    Problem 当 GUI 字段定期更新时 SWT 会冻结 我想要一个基于 SWT 的 GUI 其中文本字段的值会定期递增 最初我从单独的线程访问 textField 导致抛出异常 线程 Thread 0 org eclipse swt S
  • 异步迭代器

    我有以下代码 while slowIterator hasNext performLengthTask slowIterator next 由于迭代器和任务都很慢 因此将它们放入单独的线程中是有意义的 这是对迭代器包装器的快速而肮脏的尝试
  • 异步多播委托

    我最近在一个广泛使用事件的项目上做了一些工作 我需要做的事情之一是在多播委托上异步调用多个事件处理程序 我认为诀窍是对 GetInvocableList 中的每个项目调用 BeginInvoke 但似乎那里不存在 BeginInvoke 有
  • 使用/不使用 delegate() 启动线程

    有什么区别 new Thread new ThreadStart SomeFunc and new Thread delegate SomeFunc 这段代码在我的计算机上给出了奇怪的输出 public class A int Num pu
  • 在 Anko DSL 中创建自定义 View/ViewGroup 类

    我想创建一个自定义视图 它只是一些 Android 视图的包装 我考虑创建一个自定义 ViewGroup 来管理其子视图的布局 但我不需要这么复杂 我基本上想做的是 class MainActivity verticalLayout tex
  • 任务并行库周围是否有一个接口包装器,以便我可以将其交换用于单元测试?

    I asked 这个问题 https stackoverflow com questions 3362734 unit testing concurrent software what do you do不久以前 我现在知道这是一个坏主意
  • 如何在进入新活动之前终止线程和处理程序

    大家好 在我尝试清理处理程序时 这段代码可能有点混乱 因为我一直在尝试追踪崩溃发生的位置 我有一个对话框活动 显示密码输入 进度条由线程和处理程序动画显示 似乎当我试图查看进度条是否完成并尝试终止线程时 当我尝试进入新活动时 我这样做的方式
  • 将数据打印到文件

    我已经超载了 lt lt 运算符 使其写入文件并写入控制台 我已经为同一个函数创建了 8 个线程 并且我想输出 hello hi 如果我在无限循环中运行这个线程例程 文件中的o p是 hello hi hello hi hello hi e
  • 报告线程进度的最佳方式

    我有一个程序 它使用线程顺序执行耗时的进程 我希望能够监视每个线程的进度 类似于BackgroundWorker ReportProgress ProgressChanged模型确实如此 我不能使用ThreadPool or Backgro
  • 导航组件参数默认值

    在导航组件中 将参数从第一个片段发送到第二个片段时 默认值不会从导航图中获取哪个集合 这是我的代码 导航图 xml
  • 在 .NET 并发线程之间传递数据的最佳方式是什么?

    我有两个线程 一个需要轮询一堆单独的静态资源以查找更新 另一种需要获取数据并将其存储在数据库中 线程1如何告诉线程2有东西要处理 如果数据块是独立的 则将数据块视为要由线程池处理的工作项 使用线程池和QueueUserWorkItem将数据
  • 锁定 ASP.NET 应用程序变量

    我在 ASP NET 应用程序中使用第三方 Web 服务 对第 3 方 Web 服务的调用必须同步 但 ASP NET 显然是多线程的 并且可能会发出多个页面请求 从而导致对第 3 方 Web 服务的同时调用 对 Web 服务的调用封装在自
  • 一段时间后终止线程的最 Pythonic 方法

    我想在线程中运行一个进程 它正在迭代一个大型数据库表 当线程运行时 我只想让程序等待 如果该线程花费的时间超过 30 秒 我想终止该线程并执行其他操作 通过终止线程 我的意思是我希望它停止活动并优雅地释放资源 我认为最好的方法是通过Thre
  • 如何在 kotlin 中检查 lambda 空值

    在 Kotlin 中如何检查 lambda 是否为空 例如 我有这样的签名 onError Throwable gt Unit 我如何区分它的默认值是应用于主体还是应用于此函数的值 您无法测试 lambda 的主体是否为空 因此它不包含源代
  • 尝试在空对象引用上调用虚拟方法 -> 解析?

    我尝试使用一个按钮从一个主要活动切换到另一个活动 但是当我尝试运行该应用程序时 它在单击该应用程序后立即自行关闭 我在命令中发现错误消息 Unable to start activity ComponentInfo fr amseu mys

随机推荐