Kotlin Coroutines超时

gue*_*ter 3 kotlin kotlin-coroutines

我正在编写一个测试函数,它应该运行一个块或(当达到某个超时时)抛出一个异常.

Coroutines在Kotlin 尝试这个,但结果是CoroutinesCompletableFuture:

fun <T> runBlockWithTimeout(maxTimeout: Long, block: () -> T ): T {
    val future = CompletableFuture<T>()

    // runs the coroutine
    launch { block() }

    return future.get(maxTimeout, TimeUnit.MILLISECONDS)
}
Run Code Online (Sandbox Code Playgroud)

这有效,但我不确定这是否是解决kotlin问题的预期方法.

我也尝试过其他方法:

runBlocking {
    withTimeout(maxTimeout) {
        block()
    }
}
Run Code Online (Sandbox Code Playgroud)

但这似乎不会像block电话那样迅速起作用Thread.sleep(...)

所以是CompletableFuture办法要走的路还是有一点的吗?

更新1 我想要实现的目标:

异步集成 - 测试代码(如从RabbitMq接收数据)应该以这样的方式测试:

var rabbitResults: List = ... // are filled async via RabbitListeners
...
waitMax(1000).toSucceed {
    assertThat(rabbitResults).hasSize(1)
}
waitMax(1000).toSucceed {
    assertThat(nextQueue).hasSize(3)
}
...
Run Code Online (Sandbox Code Playgroud)

Rom*_*rov 12

withTimeout { ... }旨在取消对超时正在进行的操作,这是唯一可能的,如果有问题的操作是撤销.

它的工作原因future.get(timeout, unit)是因为它只等待超时.它实际上不会以任何方式取消或中止您的后台操作,该操作在超时后仍然继续执行.

如果你想模仿coroutines的类似行为,那么你应该等待超时,如下所示:

val d = async { block() } // run the block code in background
withTimeout(timeout, unit) { d.await() } // wait with timeout
Run Code Online (Sandbox Code Playgroud)

它可以正常工作,因为它await是一个可取消的函数,您可以通过阅读其API文档进行验证.

但是,如果您想在超时时实际取消正在进行的操作,那么您应该以异步和可取消的方式实现代码.取消是合作的,因此,首先,您在代码中使用的基础库必须提供支持取消正在进行的操作的异步API.

您可以在协同程序指南的相应部分中阅读有关取消和超时的更多信息,并观看KotlinConf的Deep Dive into Coroutines如何将协同程序与异步库集成.