如何编写 Kotlin 口语代码同步重试直到超时或成功?
Posted
技术标签:
【中文标题】如何编写 Kotlin 口语代码同步重试直到超时或成功?【英文标题】:How to write Kotlin-colloquial code to retry synchronously until timeout or success? 【发布时间】:2019-11-17 03:39:12 【问题描述】:阅读 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
,但你也必须从现有的协程中调用withTimeout
。
如果我使用正常的协程,调用函数的执行将在达到超时/成功之前继续 - 我需要防止这种情况发生。
在 Kotlin 中应该如何编码?
【问题讨论】:
【参考方案1】:您的问题可能在于doSomething()
。 Kotlin 的协程实现在很大程度上依赖于协作执行,其中子协程检查标志以查看它们是否已被取消(就像 withTimeout()
会做的那样)。这意味着外部协程将暂停,直到它们确认子协程已经结束,从而阻塞整个函数。
如果doSomething
永远不会挂起并且永远不会检查它是否仍然处于活动状态,那么无论外部情况如何,它都会一直运行直到完成。
要解决此问题,有两种选择:
-
将
doSomething()
设为suspend
函数并定期使用yield()
或ensureActive()
暂停以响应取消。
在旨在中断正常阻塞代码(如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 中实现相同的功能?我只想继续从缓冲区(锁内)读取数据,并在获得给定字节数时退出,否则在超时时退出。以上是关于如何编写 Kotlin 口语代码同步重试直到超时或成功?的主要内容,如果未能解决你的问题,请参考以下文章
java客户端调用webservice时 连接超时知道是网络原因 ,如何重试如果不重试程序就死琐了,
使用 Serverless Aurora 时 Sequelize 连接超时,寻找增加超时持续时间或重试连接的方法