gpt4 book ai didi

kotlin-coroutines - koltin,直接使用CoroutineScope和从CoroutineScope派生类有什么区别

转载 作者:行者123 更新时间:2023-12-04 01:16:57 25 4
gpt4 key购买 nike

启动协程时,它可能只是创建一个 CoroutineScope 并从中调用 launch{} -- doSomething_2()

或从 CoroutineScope 派生类并使用要启动的类{}。 -- doSomething_1()

这两种方式有区别吗?

class AClass : CoroutineScope {

override val coroutineContext: CoroutineContext = Dispatchers.Main

var theJob1: Job? = null
var theJob2: Job? = null

fun doSomething_1() {
theJob1 = launch(Dispatchers.IO) {
// ... ...
}
}

fun doSomething_2() {
theJob2 = CoroutineScope(Dispatchers.IO).launch {
// ... ...
}
}

fun dispose() {
theJob1?.cancel()
theJob2?.cancel()
}
}

最佳答案

Is there difference between these two, which way is preferred?

是的,有一个根本的区别可以使一个正确而另一个不正确。它是关于结构化并发的:如果你的 AClass 是你的“工作单元”的根对象,无论它是什么,并且负责(或观察者)它的生命周期,那么它也应该是您将在其中启动的协程的根作用域。当生命周期结束时,AClass 应该通过调用自身的 cancel 将该事件传播到协程子系统,从而取消根作用域。 CoroutineScope.cancel 是一个扩展函数。

我使用了您的代码并进行了以下修复:

  1. CoroutineScope.coroutineContext 里面必须有一个 Job() 所以我添加了它。我删除了调度程序,因为它与本文无关,而 Main 调度程序用于 GUI,而我们正在运行一个简单的测试。

  2. 我删除了您的dispose() 函数,我们有现成的cancel()

  3. 我删除了 theJob1theJob2 字段,因为一旦您开始正确使用结构化并发,它们就没有用了。

我还添加了一些代码,可以让我们观察行为:

  1. 在每个协程中添加了一个 delay 和一个 println 来查看它何时完成。

  2. 添加了一个 main 函数来测试它。该函数在最后一行永远阻塞,以便我们可以看到启动的协程将做什么。

代码如下:

import kotlinx.coroutines.*
import java.lang.Thread.currentThread
import kotlin.coroutines.CoroutineContext

fun main() {
val a = AClass()
a.doSomething_1()
a.doSomething_2()
a.cancel()
currentThread().join()
}

class AClass : CoroutineScope {

override val coroutineContext: CoroutineContext = Job()

fun doSomething_1() {
launch(Dispatchers.IO) {
try {
delay(10_000)
} finally {
println("theJob1 completing")
}
}
}

fun doSomething_2() {
CoroutineScope(Dispatchers.IO).launch {
try {
delay(10_000)
} finally {
println("theJob2 completing")
}
}
}
}

当你运行它时,你会看到只有 theJob1 完成了,而 theJob2 运行了整整 10 秒,而不是遵守 cancel信号。

这是因为构造 CoroutineScope(Dispatchers.IO) 创建了一个独立的作用域,而不是成为 AClass 作用域的子作用域,从而打破了协程层次结构。

从理论上讲,您仍然可以使用显式的 CoroutineScope 构造函数来保持层次结构,但那样的话您会得到一些显然不是首选方式的东西:

CoroutineScope(coroutineContext + Dispatchers.IO).launch {

这相当于

launch(Dispatchers.IO) {

关于kotlin-coroutines - koltin,直接使用CoroutineScope和从CoroutineScope派生类有什么区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63196192/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com