[英]Kotlin: How to bridge between blocking and asynchronous code without runBlocking?
I'm working on a project that involves computationally intensive tasks that I want to run in parallel.我正在从事一个涉及我想并行运行的计算密集型任务的项目。 To do so, I'm using multiple
async
statements to run the tasks and awaitAll
to wait until all threads completed computation.为此,我使用多个
async
语句来运行任务并awaitAll
等待所有线程完成计算。
suspend fun tasks() {
coroutineScope {
val result = List (10) {
async {
// do stuff
}
}.awaitAll()
}
}
My question is how to bridge between this code that is run in parallel and regular synchronous code.我的问题是如何在并行运行的代码和常规同步代码之间建立桥梁。
I tried to use runBlocking
but that seems to run all the async
tasks after one another, therefore defeating the whole purpose of using coroutines.我尝试使用
runBlocking
,但这似乎一个接一个地运行所有async
任务,因此违背了使用协程的全部目的。 The only way I got it to work was to use suspend
functions all the way up to the main
function, however that is not suitable in my case, as I rely on third-party libraries to call my code from regular functions.我让它工作的唯一方法是一直使用
suspend
函数直到main
function,但这对我来说不合适,因为我依赖第三方库从常规函数调用我的代码。
Is there a way to call suspend functions from regular functions while still maintaining their ability to run in parallel?有没有办法从常规函数调用挂起函数,同时仍然保持它们并行运行的能力?
The reason why subtasks were running sequentially is that by default runBlocking()
utilizes the thread that invoked it to create a single-thread dispatcher and runs all coroutines using it.子任务顺序运行的原因是默认情况下
runBlocking()
利用调用它的线程来创建单线程调度程序并使用它运行所有协程。 If your coroutines never suspend, they will be invoked sequentially.如果您的协程从不挂起,它们将被顺序调用。
In order to use another dispatcher, we simply need to pass it to runBlocking()
:为了使用另一个调度程序,我们只需要将它传递给
runBlocking()
:
runBlocking(Dispatchers.Default) { ... }
However, if you don't use coroutines already and you don't plan to suspend, but only perform CPU-intensive tasks, then I'm not sure if you can at all benefit from coroutines.但是,如果您还没有使用协程并且您不打算暂停,而只是执行 CPU 密集型任务,那么我不确定您是否完全可以从协程中受益。 Coroutines are mostly for performing tasks that often have to wait for something, so we can utilize their suspend & resume feature.
协程主要用于执行经常需要等待的任务,因此我们可以利用它们的挂起和恢复功能。 They are useful, if we need to often fork and join.
如果我们需要经常分叉和加入,它们很有用。 But if we simply need to parallelize CPU computation, then the classic approach with executors will do.
但如果我们只需要并行化 CPU 计算,那么使用执行器的经典方法就可以了。
Also, when bridging using runBlocking()
, be careful to not invoke it from the coroutine itself.此外,在使用
runBlocking()
进行桥接时,注意不要从协程本身调用它。 We can't block the thread while running inside the coroutine context.我们不能在协程上下文中运行时阻塞线程。 It could cause serious performance problems or even a deadlock.
它可能导致严重的性能问题甚至死锁。 If you invoke
runBlocking()
, and then inside it, somewhere deep into the call stack, you invoke one of your bridges again, you will run into problems.如果您调用
runBlocking()
,然后在其中调用堆栈深处的某处再次调用您的一个桥接器,您将遇到问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.