繁体   English   中英

Kotlin 协程启动{} vs 启动{ withContext{} }

[英]Kotlin Coroutine launch{} vs launch{ withContext{} }

我的 Android 应用程序需要在后台(在服务内)进行一些文件读/写,首先我使用:

CoroutineScope(Dispatchers.IO).launch {
    val fos = openFileOutput(fileName, MODE_PRIVATE)
    val oos = ObjectOutputStream(fos)
    oos.writeObject(myObj)
    oos.close()
}

块内的每一行都有一个警告:“不适当的阻塞方法调用”

搜索问题后,我认为我理解了 80%。 所以基本上大多数协程只有1个线程,如果它被阻塞,协程将没有线程来做其他工作。 要解决这个问题,我们应该像这样将它包装在withContext

CoroutineScope(Dispatchers.IO).launch {
    withContext(Dispatchers.IO) {
        val fos = openFileOutput(fileName, MODE_PRIVATE)
        val oos = ObjectOutputStream(fos)
        oos.writeObject(myObj)
        oos.close()
    }
}

Android Studio 仍然显示警告。 帖子说这只是 Android Studio 中的一个错误,这个解决方案很好。

我不明白的是, withContext仍在Dispatchers.IO上运行。 launch块来看,它可能看起来像非阻塞,但如果Dispatchers.IO只有 1 个线程并且withContext块在该线程上运行,那么该线程仍然被阻塞,不是吗?

我还了解到Dispatchers.IO实际上有无限线程,它只是在需要时创建一个新线程。 所以withContext实际上并没有阻塞,但如果这是真的,为什么我们需要withContext块? 如果Dispatchers.IO可以在需要时创建线程从而永远不会被阻塞,那么第一个代码不会有任何问题,对吧?

是的,这是一个带有警告的错误。 Lint 无法检测到 scope 使用的是什么 Dispatcher,我想他们只是假设您使用的是 scope,其上下文使用Dispatchers.Main ,因为这是最常见的。

您的 CoroutineScope(伪)构造函数具有Dispatchers.IO的上下文,因此如果不修改它, launch会继承该上下文,因此您启动的协程也使用Dispatchers.IO 所以,你的withContext块是多余的。

解决方法是在启动时指定调度程序:

CoroutineScope(Job()).launch(Dispatchers.IO) {
    val fos = openFileOutput(fileName, MODE_PRIVATE)
    val oos = ObjectOutputStream(fos)
    oos.writeObject(myObj)
    oos.close()
}

另外,你的声明:

所以基本上大多数协程只有1个线程,如果它被阻塞,协程将没有线程来做其他工作。

具有误导性。 协程没有线程,而 Dispatcher 有。 并且有些 Dispatcher 有很多线程。

似乎 Android Studio 中确实存在错误。 以下代码对我没有显示任何警告:

CoroutineScope(Dispatchers.IO).launch(Dispatchers.IO) {
    val fos = context.openFileOutput("", Context.MODE_PRIVATE)
    val oos = ObjectOutputStream(fos)
    oos.writeObject(myObj)
    oos.close()
}

您还应该知道,这段代码与您共享的两段代码在行为上几乎没有区别。 在这三种情况下,代码都将在 IO 线程上执行。

  • CoroutineScope(context)
  • launch(context)
  • withContext(context

所有这些方法都只是指定协程上下文。 默认情况下, launch使用协程 scope 上下文,但您可以像我上面所做的那样或使用withContext来更改它。

所以基本上大多数协程只有1个线程,如果它被阻塞,协程将没有线程来做其他工作。

Dispatchers.IO实际上默认为 64 个线程。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM