Kotlin Coroutines with timeout

拟墨画扇 提交于 2021-01-21 05:09:28

问题


I'm currently writing a test-function which should run a block or (when a certain timeout is reached) throws an exception.

I was trying this with Coroutines in Kotlin but ended up with a mixture of Coroutines and CompletableFuture:

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

    // runs the coroutine
    launch { block() }

    return future.get(maxTimeout, TimeUnit.MILLISECONDS)
}

This works, but I'm not sure if this is the intended way to solve that problem in kotlin.

I also tried other approaches:

runBlocking {
    withTimeout(maxTimeout) {
        block()
    }
}

But this seems not to work as soon as the block calls e.g. Thread.sleep(...)

So is the CompletableFuture approach the way to go or is there a better one?

update 1 What I want to achieve:

Async Integration-Test code (like receiving data from RabbitMq) should be tested somehow like this:

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

回答1:


withTimeout { ... } is designed to cancel the ongoing operation on timeout, which is only possible if the operation in question is cancellable.

The reason it works with future.get(timeout, unit) is because it only waits with timeout. It does not actually cancel or abort in any way your background operation which still continues to execute after timeout had elapsed.

If you want to mimick similar behavior with coroutines, then you should wait with timeout, like this:

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

It works properly because await is a cancellable function which you can verify by reading its API documentation.

However, if you want to actually cancel the ongoing operation on timeout, then then you should implement your code in asyncronous and cancellable way. Cancellation is cooperative, so, to start, the underlying library that you are using in your code has to provide asynchronous API that supports cancellation of ongoing operation.

You can read more about cancellation and timeouts in the corresponding section of the coroutines guide and watch the KotlinConf's Deep Dive into Coroutines on how to integrate coroutines with asynchronous libraries.



来源:https://stackoverflow.com/questions/47635367/kotlin-coroutines-with-timeout

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!