android 如果从协程调用一个非挂起函数会发生什么?

ugmeyewa  于 2022-12-31  发布在  Android
关注(0)|答案(3)|浏览(132)

Kotlin中关于协程的一个关键概念是suspend函数必须从协程或另一个suspend函数调用。
但是,suspend函数可以调用任何类型的函数,suspend或normal。
那会有什么后果?(这不是我拥有的真实的场景,只是出于理论原因想知道)
我想在那种情况下,创建协程的唯一目的就是在调用它之前改变上下文(线程),这样它就不会阻塞主线程。然而,协程的所有其他优点会失去吗?(合作取消,结构化并发...)

dpiehjr4

dpiehjr41#

如果一个挂起的函数调用另一个挂起的函数,那么协程将被挂起,直到返回结果。
从一个挂起的函数调用一个常规函数会阻塞线程。哪个线程?嗯,这取决于你使用的调度器。IO能够产生数百个线程。但是Default调度器的线程数量与你的CPU数量相同。这意味着虽然这不会阻塞其他协程,但会减少可用资源的数量。
含义:不要调用非挂起函数,因为它可能会在这个调度器上阻塞很长一段时间,就像不要阻塞UI线程一样。
是的,挂起函数可能会产生相同的结果,如果你正在做一个没有yield()或任何其他挂起调用的忙碌循环。

iezvtpos

iezvtpos2#

挂起函数可以在中间挂起,稍后再继续。从挂起函数调用普通函数将失去暂停执行的能力。
当一个挂起函数被编译时,Kotlin编译器在参数中加入一个延续对象作为参数。这个延续对象是挂起一个协同程序所需要的。当一个挂起函数调用另一个挂起函数时,它传递这个延续对象,这与协同程序一样。
如果一个非挂起函数被挂起函数调用,你就不能使用那个函数的协同例程了......就是这样

sh7euo9m

sh7euo9m3#

然而,协程的所有其他优点会丧失吗?(协作取消、结构化并发......)
即使是不可挂起的函数也可以通过显式地检查CoroutineContext.isActive标志来参与协作取消,尽管这更多的是一个理论上的事实。
如果一个函数执行了一个阻塞IO操作,它将不会响应取消请求。该操作必须自己完成。
至于结构化并发,与您所关心的几乎相反:Kotlin的最佳实践是从一个 non-suspendable 函数启动子协程,而这个函数是CoroutineScope上的一个扩展,并调用协程构建器,将它作为接收器。

相关问题