gpt4 book ai didi

kotlin协程withTimeout在使用withContext获取非阻塞代码时不取消

转载 作者:行者123 更新时间:2023-12-02 12:53:03 26 4
gpt4 key购买 nike

我正在使用 withContext 将函数转换为不会阻塞调用线程的挂起函数。
为此,我使用了 https://medium.com/@elizarov/blocking-threads-suspending-coroutines-d33e11bf4761作为引用。

现在我想用超时调用这个函数。为此,我使用 withTimeout 来调用该函数:

@Test
internal fun timeout() {
runBlocking {
logger.info("launching")
try {
withTimeout(1000) {
execute()
}
} catch (e: TimeoutCancellationException) {
logger.info("timed out", e)
}
}
}

private suspend fun execute() {
withContext(Dispatchers.IO) {
logger.info("sleeping")
Thread.sleep(2000)
}
}

所以我希望在 1000 毫秒后取消异步启动的协程并抛出 TimeoutCancellationException。
但是发生的情况是完整的 2000 毫秒通过,并且当协程完成时抛出异常:

14:46:29.231 [main @coroutine#1] INFO b.t.c.c.CoroutineControllerTest - launching
14:46:29.250 [DefaultDispatcher-worker-1 @coroutine#1] INFO b.t.c.c.CoroutineControllerTest - sleeping
14:46:31.261 [main@coroutine#1] INFO b.t.c.c.CoroutineControllerTest - timed out kotlinx.coroutines.TimeoutCancellationException: Timed out waiting for 1000 ms at kotlinx.coroutines.TimeoutKt.TimeoutCancellationException(Timeout.kt:128) at kotlinx.coroutines.TimeoutCoroutine.run(Timeout.kt:94) at kotlinx.coroutines.EventLoopImplBase$DelayedRunnableTask.run(EventLoop.kt:307) at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.kt:116) at kotlinx.coroutines.DefaultExecutor.run(DefaultExecutor.kt:68) at java.lang.Thread.run(Thread.java:748)



我用错了吗?

或者也许这是预期的行为?在文档中,计数器也变为 2,这意味着在取消协程之前已经过去了 1500 毫秒:
https://github.com/Kotlin/kotlinx.coroutines/blob/master/docs/cancellation-and-timeouts.md#timeout

最佳答案

如果您启动子协程并等待其完成,您可以在超时后取得进展:

fun timeout() {
runBlocking {
logger.info("launching")
try {
withTimeout(100) {
execute()
}
} catch (e: TimeoutCancellationException) {
logger.info("timed out", e)
}
}
}

private suspend fun execute() =
GlobalScope.launch(Dispatchers.IO) {
logger.info("sleeping")
Thread.sleep(2000)
}.join()

有了这个,你已经将阻塞的子协程与你在其中的调度程序解耦了 join()它,所以 suspend fun join()可以立即对取消使用react。

请注意,这更像是一种解决方法,而不是完整的解决方案,因为 IO 中的线程之一在 sleep() 之前,调度程序仍将保持阻塞状态。过期。

关于kotlin协程withTimeout在使用withContext获取非阻塞代码时不取消,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56305044/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com