我需要我的代码运行一个块并在 1 秒后返回值以防超时但让它完成工作。我设法实现了一些有效的东西,但 IDE 建议替换为async,withContext(DefaultDispatcher)但它的工作方式不一样。
所以我的问题是如何让它在没有 IDE 警告的情况下工作。我是 Kotlin Coroutines 的新手,所以我可能在这里遗漏了一些东西。
@Test
fun how_timeout_with_null_works() = runBlocking<Unit> {
val time = measureTimeMillis {
println("Start test")
val result = withTimeoutOrNull(1, TimeUnit.SECONDS) {
async { doSomeHardWork() }.await()
}
println("End test $result")
}
println("Time $time")
delay(3000)
}
private suspend fun doSomeHardWork(): String {
println("start hard work")
Thread.sleep(2000)
print("end hard work")
return "[hard work done]"
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,IDE 会给出警告,因为async(ctx) { ... }.await()通常是一个错误,并且withContext(ctx) { ... }通常更好地反映了代码作者的原始意图。
对于您的代码,您的意图是不同的。您的意图是等待1 秒,而不限制您的doSomeHardWork代码。但是,您的代码结构并不反映您的意图。您已将整个块包裹起来withTimeout并放入doSomeHardWork其中,而您的意图只是进行限时等待。因此,如果您以代码结构与您的意图相匹配的方式重写代码,它将在没有任何警告的情况下工作:
val work = async { doSomeHardWork() } // start work
val result = withTimeoutOrNull(1, TimeUnit.SECONDS) { work.await() } // wait with timeout
Run Code Online (Sandbox Code Playgroud)
如果您碰巧不止一次需要这种代码模式,那么您可以为自己定义一个方便的扩展:
suspend fun <T> Deferred<T>.awaitWithTimeout(time: Long, unit: TimeUnit): T? =
withTimeoutOrNull(time, unit) { await() }
Run Code Online (Sandbox Code Playgroud)
然后编写更好的代码来反映您的意图:
val result = async { doSomeHardWork() }.awaitWithTimeout(1, TimeUnit.SECONDS)
Run Code Online (Sandbox Code Playgroud)
不过要小心。您开始使用的这些协程async将在等待超时后继续运行。这很容易导致资源泄漏,除非您采取措施限制并发运行的后台作业的数量。
| 归档时间: |
|
| 查看次数: |
934 次 |
| 最近记录: |