如何编写Kotlin口语代码以同步重试,直到超时或成功?

时间:2019-07-07 09:56:19

标签: android kotlin kotlin-coroutines

在阅读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()
    }
}

timeoutMsL是一个Long,典型值为50毫秒。 该代码是通过JNI从C ++调用的。当我运行它

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

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

如何用Kotlin进行编码?

1 个答案:

答案 0 :(得分:1)

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

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

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

  1. doSomething()一个suspend函数,并定期yield()ensureActive()暂停以响应取消。
  2. 在旨在中断正常阻止代码(例如withContext(Dispatchers.IO))的调度程序上执行该命令。