与上下文和挂起可取消协程之间的区别



我是协程的新手

这是一个流行的例子:

suspend fun findBigPrime(): BigInteger =
withContext(Dispatchers.IO) {
BigInteger.probablePrime(4096, Random()))
}

但是,它可以写成:

suspend fun findBigPrime(): BigInteger =
suspendCancellableCoroutine {
it.resume(BigInteger.probablePrime(4096, Random()))
}

真正的区别是什么?

> 真正的区别是什么?

事实上,几乎没有任何关系。

suspendCancellableCoroutine {
it.resume(BigInteger.probablePrime(4096, Random()))
}

这只会在简单的直接调用之上增加无用的开销

BigInteger.probablePrime(4096, Random())

如果在仍在suspendCancellableCoroutine块内恢复继续,则协程根本不会挂起。

withContext(Dispatchers.IO) {
BigInteger.probablePrime(4096, Random()))
}

这会挂起协程并在另一个线程上启动内部协程。当内部协程完成时,它会恢复当前协程并显示结果。

在这里使用suspendCancellableCoroutine是一个"大不"。

withContext更改块(协程(将在其上运行的上下文,此处将覆盖将协程调度到指定线程的调度程序。虽然suspendCoroutine/suspendCancellableCoroutine用于包装异步回调,但异步回调不会阻塞线程,而是在自己的线程上运行。

通常suspendCoroutine/suspendCancellableCoroutine的工作是非阻塞的,并且很快就会完成,并且在工作以非阻塞方式完成后恢复继续,也许在其他线程中

。如果你把阻塞代码放在那里,协程的概念就会丢失,它只会阻塞它正在运行的线程。

suspendCoroutine/suspendCancellableCoroutine的使用:

// This function immediately creates and starts thread and returns
fun findBigPrimeInNewThread(after: (BigInteger) -> Unit) {
Thread {
BigInteger.probablePrime(4096, Random()).also(after)
}
}
// This just wraps the async function so that when the result is ready resume the coroutine
suspend fun findBigPrime(): BigInteger =
suspendCancellableCoroutine { cont ->
findBigPrimeInNewThread {
cont.resume(it)
}
}

最新更新