Kotlin中协程的关键概念之一是必须从协程或另一个暂停函数调用暂停函数。
但是,暂停函数可以调用任何类型的函数,无论是暂停还是正常。
那会有什么后果? (这不是我遇到的真实情况,只是出于理论原因想知道)
我想在这种情况下,创建协程的唯一目的就是在调用上下文之前更改上下文(线程),因此它不会阻塞主线程。 但是,协程的所有其他优势会消失吗? (合作取消,结构化并发...)
答案 0 :(得分:0)
如果一个挂起函数调用另一个挂起函数,则协程将被挂起,直到返回结果。
从挂起函数中调用常规函数将阻塞线程。哪个线程?好吧,这取决于您使用的Dispatcher。 IO
能够产生一百个线程。但是Default
调度程序的线程数量与CPU数量相同。这意味着虽然这不会阻止其他协程,但是会减少可用资源的数量。
含义:请不要调用可能在此分派器上长时间阻塞的非暂停函数,就像您没有阻塞UI
线程一样。
是的,如果您执行的是没有yield()
或其中没有任何其他暂停调用的繁忙循环之类的操作,则暂停功能可能会产生相同的结果。
答案 1 :(得分:0)
挂起功能可以在它们之间挂起,以后再恢复。从暂停函数调用普通函数会失去暂停执行的能力。
编译暂停函数时,kotlin编译器会在参数中添加一个延续对象作为参数。挂起协程需要此连续对象。当一个暂停函数调用另一个暂停函数时,它会传递延续对象,这与协同例程相同。
如果从暂停函数中调用了一个非暂停函数,那么您将无法使用该函数中的协例程...就是这样
答案 2 :(得分:0)
但是,协程的所有其他优势会消失吗? (合作取消,结构化并发...)
即使是不可暂停的函数也可以通过显式检查CoroutineContext.isActive
标志来参与协作取消。不过,这更多是理论上的事实。
如果功能执行阻塞IO操作,它将不会响应取消请求。该操作必须自己完成。
关于结构化并发,您所关心的几乎完全相反:科特林(Kotlin)最佳实践是从不可暂停函数启动子协程,该函数是{{1}的扩展},并以此作为协程生成器的接收者。