简体   繁体   English

Kotlin:如何在没有 runBlocking 的情况下桥接阻塞代码和异步代码?

[英]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.

相关问题 Kotlin runBlocking在背景线程 - Kotlin runBlocking on background thread 限制异步请求而不阻塞 - Limiting asynchronous requests without blocking 如何在不阻塞代码的情况下等待BLE回调 - How to wait BLE callback without blocking code Python Twisted异步调度而无阻塞 - Python Twisted asynchronous scheduling without blocking 如何在应用程序启动期间在后台线程上执行异步过程而不会阻塞? - How to perform asynchronous procedures on a background thread during application startup without blocking? kotlin 中的并行调用而不阻塞主线程 - parallel calls in kotlin without blocking main thread 如何使用异步事件管理线程的阻塞和解除阻塞? - How to manage thread blocking and unblocking with asynchronous events? Kotlin 协程为什么以及如何防止线程阻塞,即使没有“暂停”关键字? - Why and how Kotlin coroutine prevents blocking of a thread, even without “suspend” keyword? 如何在不阻塞主线程的情况下暂停 C# 代码执行? - How to Pause C# code execution without blocking main thread? 如何在不阻塞当前代码路径的情况下获取ExecutorService的执行结果? - How to get the execution results of ExecutorService without blocking the current code path?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM