【问题标题】:Kotlin coroutines Inappropriate blocking method call (tcp sockets)Kotlin coroutines 不恰当的阻塞方法调用(tcp sockets)
【发布时间】:2020-09-17 14:37:17
【问题描述】:

我在使用套接字时收到此警告。我正在从 IO 范围协程调用 startConnection 方法,如果 startConnection 方法被挂起,我会收到警告。我将其设为挂起,因为稍后我会从中调用其他一些挂起方法。有什么办法可以解决这个问题还是我应该取消警告?

private suspend fun startConnection(ip: String, port: Int) {
    try {
        socket = Socket(ip, port)
        .
        .           

【问题讨论】:

  • 协程永远不应该调用阻塞函数。无论您如何调用此函数,您都应始终确保在 IO 调度程序中启动阻塞代码。使用socket = withContext(Dispatchers.IO) { Socket(ip, port) }
  • 我尝试了你的解决方案,但它仍然抛出相同的警告:不适当的阻塞方法调用
  • 只要函数是“暂停”,警告就会一直存在。
  • 我没有看到此代码的任何此类警告:private suspend fun startConnection(ip: String, port: Int) = withContext(Dispatchers.IO) { val socket = Socket(ip, port) }
  • 这不是完全相同的代码,您使用IO 作为调度程序。如果这不是Dispatchers.IO 的导入快捷方式,例如val IO = Dispatchers.IO,则检查失败。

标签: android kotlin kotlin-coroutines


【解决方案1】:

Socket() 是一个 IO 调用。它正在建立一个实际的 TCP 连接。 事实上,“旧 IO”框架中的所有调用都是阻塞调用。您需要为每个调用分配一个线程(或者可以锁定一段时间)

协程 != 线程

如果您使用 Dispatch.IO,那么协程 == 线程(有点类似,但对您隐藏),但编译器不知道您使用的是调度程序,因此您将继续收到相同的错误。如果你 100% 确定你的协程在它自己的线程上,那么就忽略它。

一些不请自来的建议:如果您使用像线程这样的协程,也许只使用线程会更好?使用协程似乎让你的生活变得更加艰难(例如这个错误)。如果您使用 Dispatch.IO,您无论如何都必须同步内容,就像线程一样。不确定这里有什么协程。

协程只是一种编译器技巧,用于拆分代码并在您不知道的情况下从挂起调用中进行回调。我认为它们是 1994 年 Windows 3.1 的协作线程(旧的又是新的)。

您想了解协程的精神,请使用 NIO 调用。异步版本更易于使用(您不必编写自己的 select() 循环)。或者使用 Netty,它一直都是回调,然后围绕它包装你的协程(现在必须有一个库可以做到这一点......)

【讨论】:

    猜你喜欢
    • 2021-03-01
    • 2020-04-28
    • 2020-06-27
    • 1970-01-01
    • 2019-04-10
    • 1970-01-01
    • 2020-01-25
    • 2018-12-29
    • 2020-04-22
    相关资源
    最近更新 更多