【问题标题】:How to write Kotlin-colloquial code to retry synchronously until timeout or success?如何编写 Kotlin 口语代码同步重试直到超时或成功?
【发布时间】:2023-03-17 01:45:01
【问题描述】:

阅读 Kotlin 文档后,我想出了以下代码(它不起作用 - 见下文)重复函数调用,直到它返回 true 或达到超时。
我想暂停执行,直到此代码块超时或成功 - 它不应该异步执行。

Log.d(TAG, "This is the last line to be logged")
runBlocking {
    Log.d(TAG, "this line is never logged")
    try {
        withTimeout(timeoutMsL) {
            while ((isActive) && (!success)) {
                success = doSomething()
            }
        } 
    }
    catch (ex: TimeoutCancellationException) {
        Log.d(TAG, "this line is never logged either")
        doSomethingElse()
    }
}

timeoutMsLLong,典型值为 50 毫秒。 此代码通过 JNI 从 C++ 调用。当我运行它时

  • runBlocking 块内没有任何内容运行
  • runBlocking 块运行后什么都没有
  • 控制权返回给 C++ 调用者
  • JNI 中存在异常,但 JNI 不记录 Kotlin 或 Java 异常详细信息。
  • adb 中没有记录异常
  • 当我尝试使用 try/catch/log 块包围上述代码 sn-p 以捕获 Kotlin 异常时,没有记录任何内容

我已经读到应该避免使用runBlocking,但你也必须从现有的协程中调用withTimeout
如果我使用正常的协程,调用函数的执行将在达到超时/成功之前继续 - 我需要防止这种情况发生。

在 Kotlin 中应该如何编码?

【问题讨论】:

    标签: android kotlin kotlin-coroutines


    【解决方案1】:

    您的问题可能在于doSomething()。 Kotlin 的协程实现在很大程度上依赖于协作执行,其中子协程检查标志以查看它们是否已被取消(就像 withTimeout() 会做的那样)。这意味着外部协程将暂停,直到它们确认子协程已经结束,从而阻塞整个函数。

    如果doSomething 永远不会挂起并且永远不会检查它是否仍然处于活动状态,那么无论外部情况如何,它都会一直运行直到完成。

    要解决此问题,有两种选择:

    1. doSomething() 设为suspend 函数并定期使用yield()ensureActive() 暂停以响应取消。
    2. 在旨在中断正常阻塞代码(如withContext(Dispatchers.IO))的调度程序上执行它。

    【讨论】:

    • 我以为我用这行代码覆盖了这种可能性:while ((isActive) && (!success)) {.它检查 withTimeout 协程中的 IsActive 参数。
    • 它需要doSomething() 在该代码运行之前返回,如果它永远不会返回该代码永远不会运行。
    • doSomething 是一个简短的函数。它应该返回。我在此代码之前添加了一个带有单个日志记录行的小型 runBlocking 块,并且此行也从未记录过。出于某种原因,我的代码每次遇到 runBlocking 时都会退出。我不明白发生了什么。
    • 感谢您的回复。隐含地,您已经确认我的代码是正确的。该代码位于 AAR 中,该 AAR 是 Xamarin Android 绑定库的一部分。我现在已经证明 Xamarin 不能识别 Kotlin 协程。我找不到任何支持它们的 Xamarin 库(相当于 Xamarin 的 org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.1)
    • 最后一个问题——如何在不使用协同程序的情况下在 Kotlin 中实现相同的功能?我只想继续从缓冲区(锁内)读取数据,并在获得给定字节数时退出,否则在超时时退出。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多