Kotlin Channel无法正常结束:无需cancelChildren()如何实现自然终止?
Kotlin Channel produce扩展函数疑问:无需cancelChildren()如何让代码自然结束?
我是Kotlin Channel的新手,以下是使用produce扩展函数(返回ReceiveChannel)的练习代码。在repeat(10)的每次循环中,变量cur会被重新赋值为新的ReceiveChannel,因此我在filter扩展函数中调用了cancel()方法。
初始代码(未正常结束)
我原本期望代码能正常结束,但实际并未实现:
fun CoroutineScope.numbersFrom(start: Int) = produce<Int> { var x = start while (true) send(x++) // 无限发送从start开始的整数 } fun CoroutineScope.filter(numbers: ReceiveChannel<Int>, prime: Int) = produce<Int> { for (x in numbers) if (x % prime != 0) send(x) numbers.cancel() // 在此处取消 } fun main() { runBlocking { var cur = numbersFrom(2) // 无限发送数字... repeat(10) { val prime = cur.receive() // 只获取一个元素 println(prime) cur = filter(cur, prime) // 新的接收通道 } cur.cancel() // 在此处取消 } }
尝试修改后抛出异常
我尝试了以下代码,但运行时出现异常:
Exception in thread "main" kotlinx.coroutines.JobCancellationException: BlockingCoroutine was cancelled; job=BlockingCoroutine{Cancelled}@26a7b76d
代码如下:
fun CoroutineScope.numbersFrom(start: Int) = produce<Int> { var x = start while (true) send(x++) // 无限发送从start开始的整数 } fun CoroutineScope.filter(numbers: ReceiveChannel<Int>, prime: Int) = produce<Int> { for (x in numbers) if (x % prime != 0) send(x) numbers.cancel() } fun main() { runBlocking { var cur = numbersFrom(2) // 无限发送数字... repeat(10) { val prime = cur.receive() // 只获取一个元素 println(prime) cur = filter(cur, prime) // 新的接收通道 } cur.cancel() coroutineContext.cancel() } }
使用cancelChildren()可正常结束的代码
此外,以下代码通过取消所有子协程可以自然结束:
fun CoroutineScope.numbersFrom(start: Int) = produce<Int> { var x = start while (true) send(x++) // 无限发送从start开始的整数 } fun CoroutineScope.filter(numbers: ReceiveChannel<Int>, prime: Int) = produce<Int> { for (x in numbers) if (x % prime != 0) send(x) numbers.cancel() } fun main() { runBlocking { var cur = numbersFrom(2) // 无限发送数字... repeat(10) { val prime = cur.receive() // 只获取一个元素 println(prime) cur = filter(cur, prime) // 新的接收通道 } coroutineContext.cancelChildren() } }
请问有没有不使用coroutineContext.cancelChildren()就能让代码自然结束的方法?
内容的提问来源于stack exchange,提问作者Hyun
相关产品推荐
相关产品推荐

