我想在同一协程中继续动态代理中的挂起功能。请看下面的代码:
interface Adder {
suspend fun add(a: Int, b: Int): Int
}
val IH = InvocationHandler { _, method, args ->
val continuation = args.last() as Continuation<*>
val realArgs = args.take(args.size - 1)
println("${method.name}$realArgs")
GlobalScope.launch {
delay(5_000)
@Suppress("UNCHECKED_CAST") (continuation as Continuation<Int>).resume(3)
}
COROUTINE_SUSPENDED
}
fun main() {
val adder = Proxy.newProxyInstance(
Adder::class.java.classLoader, arrayOf(Adder::class.java), IH
) as Adder
runBlocking {
println(adder.add(1, 2))
}
}它工作得很好。它在一个新的协程中运行延迟函数。然而,这不是我想要的。
我想在与runBlocking启动时相同的协程中运行InvocationHandler。类似于:
val IH = InvocationHandler { _, _, _ ->
delay(5_000)
3
}这显然无法编译,因为延迟是一个必须在协程中运行的挂起函数。所以问题是:我如何才能为我的预期行为编写InvocationHandler?任何帮助都将不胜感激。
我想在我的RPC框架中使用这段代码。我的实际代码将使用非阻塞Ktor套接字调用替换延迟调用,以便通过网络序列化数据。您可以在https://raw.githubusercontent.com/softappeal/yass/master/kotlin/yass/test/ch/softappeal/yass/remote/SuspendProxy.kt中找到代码示例
发布于 2019-02-02 22:58:28
我已经为我的问题找到了解决方案:
package ch.softappeal.yass
import kotlinx.coroutines.*
import java.lang.reflect.*
import kotlin.coroutines.*
import kotlin.test.*
typealias SuspendInvoker = suspend (method: Method, arguments: List<Any?>) -> Any?
private interface SuspendFunction {
suspend fun invoke(): Any?
}
private val SuspendRemover = SuspendFunction::class.java.methods[0]
@Suppress("UNCHECKED_CAST")
fun <C : Any> proxy(contract: Class<C>, invoker: SuspendInvoker): C =
Proxy.newProxyInstance(contract.classLoader, arrayOf(contract)) { _, method, arguments ->
val continuation = arguments.last() as Continuation<*>
val argumentsWithoutContinuation = arguments.take(arguments.size - 1)
SuspendRemover.invoke(object : SuspendFunction {
override suspend fun invoke() = invoker(method, argumentsWithoutContinuation)
}, continuation)
} as C
interface Adder {
suspend fun add(a: Int, b: Int): Int
}
class SuspendProxyTest {
@Test
fun test() {
val adder = proxy(Adder::class.java) { method, arguments ->
println("${method.name}$arguments")
delay(100)
3
}
runBlocking { assertEquals(3, adder.add(1, 2)) }
}
}有什么意见吗?
这是一个好的/有问题的解决方案吗?
可以/应该将“删除挂起功能”添加到kotlin.coroutines库中吗?
发布于 2019-02-01 06:07:36
在InvocationHandler中使用runBlocking
val IH = InvocationHandler { _, _, _ ->
runBlocking{
delay(5_000)// now you can use suspend functions here
}
3
}https://stackoverflow.com/questions/54467556
复制相似问题