我正在使用公开了回调函数的第三方库。成功时将调用回调函数。回调函数不是挂起函数,但是当我尝试在非挂起函数内部进行调用以返回挂起函数的结果时,该结果使用aysnc和await进行IO调用,因此该调用永远不会被强制执行。下面,我提出了一个简单的代码片段来演示该问题。
select * from sample where some_pk =1 and some_id <= 124 limit x;
如果我在makeSuspendFunCall中删除了延迟功能,程序运行会很好,但是如果添加延迟功能,它将被挂起。我实际上是在这里使用延迟功能来模拟暂停功能的网络调用。在这种情况下,如何从awaitBlockingExample获得结果?我清楚地了解到,通过将awaitBlockingExample设置为suspend函数,我可以使它工作并删除异步并在其中运行阻塞调用。但是这里awaitBlockingExample(非暂挂函数)表示此方库提供的实现,该方库在我们的实现中被覆盖。例如,番石榴缓存提供了一个重载功能,我想重写重载功能(非暂停功能)并从重载方法中调用协程函数来刷新数据库或网络调用中的缓存值。
答案 0 :(得分:3)
问题在于vertx.dispatcher()
使用单个线程作为事件循环,而runBlocking
阻塞了该线程。
详细信息:
您的awaitBlockingExample()
函数正在此Vertx事件循环线程上运行,因为它是由suspend start()
函数触发的。如果您调用runBlocking()
,则此Vertx线程将被阻止并且永远不会释放。但是您的其他协程,例如async()
,现在没有线程可以完成工作。
解决方案:
我假设从awaitBlockingExample
函数调用start
仅在此示例中发生。实际上,我会假设外部回调使用自己的线程。那就根本没有问题,因为现在外部线程被阻塞了:
override suspend fun start() {
//simulate own thread for external callback
thread {
awaitBlockingExample()
}
}
fun awaitBlockingExample():String {
val future= async(vertx.dispatcher()) {
makeSuspendFunCall()
}
val result:String= runBlocking(vertx.dispatcher()){future.await()}
println(" The final Result is $result")
return result
}
顺便说一句:您不需要async()
块,可以直接从makeSuspendFunCall()
调用runBlocking()
fun awaitBlockingExample():String = runBlocking(vertx.dispatcher()){
val result = makeSuspendFunCall()
println(" The final Result is $result")
result
}
答案 1 :(得分:0)
尝试下一种方法:
override fun start() {
GlobalScope.launch {
val result = awaitBlockingExample()
}
}
suspend fun awaitBlockingExample(): String {
val response = makeSuspendFunCall()
println(" The final Result is $response")
return response
}
suspend fun makeSuspendFunCall():String{
println("Comming here 3")
return suspendCoroutine {
delay(500)
val resp="Test"
it.resume(resp)
}
}
答案 2 :(得分:0)
对于Kotlin 1.3.0及更高版本
private val mainScope = CoroutineScope(Dispatchers.Main)
fun start(){
mainScope.launch {
val data = withContext(Dispatchers.IO){
//This function will return the result. Return type of the below function will be type of data variable above.
awaitBlockingExample()
}
//use your data result from async call. Result will be available here as soon as awaitBlockingExample() return it.
}
//Your function will continue execution without waiting for async call to finish.
}
fun awaitBlockingExample():String {
//Your Logic
}
希望这会有所帮助。