【问题标题】:JobCancellationException UndispatchedCoroutine error in KotlinKotlin 中的 JobCancellationException UndispatchedCoroutine 错误
【发布时间】:2020-06-16 14:09:41
【问题描述】:

我对协程还是很陌生(但已经非常喜欢它们了)。我有这个错误(和崩溃),不知道这意味着什么。什么是 UndispatchedCoroutine?怎么取消的?

kotlinx.coroutines.JobCancellationException: UndispatchedCoroutine 被取消; job="coroutine#8":UndispatchedCoroutine{Cancelled}@fe7d397

编辑: 为了提供一些上下文,我使用一个 Actor 在协程中执行消息处理:

@OptIn(kotlinx.coroutines.ObsoleteCoroutinesApi::class)
internal inner class HandlerFPMsg : Handler() {
    private val msgActor = coroutineScope.actor<Pair<Int, Long>>(Dispatchers.Default, capacity = Channel.UNLIMITED) {
        for(msg in channel)
            handleMessageWorker(msg.first, msg.second)
    }

    override fun handleMessage(msg: Message) {
        msgActor.offer(Pair(msg.what, msg.data.getLong("ID",-1L)))
        super.handleMessage(msg)
    }

    private suspend fun handleMessageWorker(what: Int, id: Long) {
        if (what != 0x92) Log.d("Messenger123", "Message Received: [" + what.toString(16) + "]")
        when (what) {
            MsgConstants.MSG_CONSTANT1 -> {
                someFunction()
                Log.e(TAG, "${e.message}")
            }
            MsgConstants.MSG_CONSTANT2 -> {
                if (id != lastId) return
                // -----------------------
                if (aSuspendingFunction()) {
                    msgService?.let { msgr -> aClass.sendAmsg(msgr) }
                } else {
                    // some comment 
                    someFunction()
                }
            }
        }
    }
}

如果我用 try catch 块包装 handleMessageWorker(msg.first, msg.second) 似乎可以工作(但我不知道代码的正确性如何......)

【问题讨论】:

  • Undispatched 协程是一种可以在同一个调度程序上嵌套上下文的状态,这本身不是问题。你的代码到底是做什么的?
  • @AlexeySoshin 我更新了我的问题

标签: android kotlin kotlin-coroutines


【解决方案1】:

这不是一个确定的答案,但我发现 cmets 太短了。

从这是一个内部类的事实来看,并且您正在使用 coroutineScope 从外部创建您的 actor,我的猜测是您的 coroutineScope 被终止,这也终止了您的演员。这是结构化并发的正确行为。

问题是:为什么你的协程作用域会被终止。

两种主要可能性:

  1. 它绑定到另一个对象的生命周期。如果您从 Android Activity 的范围内启动此 Actor,则 coroutineScope 可能会在活动关闭后终止。
  2. 使用相同范围的另一段代码引发异常。这也会导致作用域终止,除非它是supervisorScope

【讨论】:

  • 肯定是第二个,因为我使用的 coroutineScope 是服务 MyService : LifecycleService() 之一,所以我从中得到 lifecycleScope 并且服务已启动并正在运行(前台服务以 startService 和边界)。但我无法理解是什么真正触发了我使用选项System.setProperty(DEBUG_PROPERTY_NAME, DEBUG_PROPERTY_VALUE_ON) 获得的堆栈跟踪异常
  • 我建议尝试supervisorScope,看看你是否得到了任何你可能会丢失的堆栈恍惚。
猜你喜欢
  • 1970-01-01
  • 2021-04-23
  • 2020-06-29
  • 1970-01-01
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-07
相关资源
最近更新 更多