You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android/Windows平台Kotlin协程表现不一致问题求助

Kotlin协程跨平台(Android/Windows)执行差异问题解决

问题背景

使用Kotlin开发Android/Windows远程控制应用(客户端+服务端),相同代码在Android平台运行正常,但在Windows平台无预期执行效果。熟悉Android协程基础,但对桌面平台协程处理逻辑不了解。

核心代码

Main.kt

fun main(): Unit = runBlocking {

    CoroutineScope(Job()).launch {
        println("connecting server")
        Servidor.ligar()
    }

    CoroutineScope(Job()).launch {
        println("connecting client")
        Cliente.ligar()

    }

}

Server.kt

object Servidor {

    suspend fun ligar() = withContext(Dispatchers.IO) {

        val porta = 1777
        var mensagem: String

        val server = ServerSocket(porta)
        println("Trying to connect through $porta...")

        val client = server.accept()
        val mPrintWriter = PrintWriter(client.getOutputStream(), true)

        val br = BufferedReader(InputStreamReader(client.getInputStream()))
        println("Connected by port: $porta")

        while (br.readLine().also { mensagem = it } != null) {
            println("The message: $mensagem")
            if (mensagem == "bye") {
                mPrintWriter.println("bye")
                break
            } else {
                mensagem = "Server returns $mensagem"
                mPrintWriter.println(mensagem)
            }
        }
        mPrintWriter.close()
        br.close()

        client.close()
    }
}

Cliente.kt

object Cliente {

    suspend fun ligar() = withContext(Dispatchers.IO) {

        val portNumber = 1777
        var str = "initialize"

        val mSocket = Socket(InetAddress.getLocalHost(), portNumber)
        val br = BufferedReader(InputStreamReader(mSocket.getInputStream()))
        val pw = PrintWriter(mSocket.getOutputStream(), true)

        pw.println(str)
        println(str)

        while (br.readLine().also { str = it } != null) {
            println(str)
            pw.println("bye")
            if (str == "bye") break
        }
        br.close()
        pw.close()
        mSocket.close()
    }

}

执行结果对比

  • Android平台(Logcat输出):
connecting server
connecting client
Trying to connect through 1777...
initialize
Connected by port: 1777
The message: initialize
Server returns initialize
The message: bye
bye
  • Windows平台(IntelliJ IDEA输出):
connecting server
connecting client

Process finished with exit code 0

问题原因

在Windows平台的runBlocking作用域中,通过CoroutineScope(Job())创建的协程作用域与runBlocking的根Job无父子关联。runBlocking仅会等待自身作用域内的代码执行完毕,当两个launch调用完成后,程序直接退出,导致后续的Socket连接、数据交互逻辑还未执行就被终止。

而Android平台通常使用与组件生命周期绑定的协程作用域(如lifecycleScope),这类作用域会自动管理协程生命周期,等待协程执行完成,因此代码能正常运行。

解决方案

方案1:直接在runBlocking作用域内启动协程

移除独立的CoroutineScope(Job()),直接使用runBlocking的作用域启动协程,此时协程会成为runBlocking的子协程,runBlocking会等待所有子协程执行完毕后再退出:

fun main(): Unit = runBlocking {

    launch {
        println("connecting server")
        Servidor.ligar()
    }

    launch {
        println("connecting client")
        Cliente.ligar()
    }

}

方案2:关联协程Job并手动等待

如果需要保留独立的CoroutineScope,可将其Job与runBlocking的上下文绑定,或保存launch返回的Job实例并手动调用join()等待完成:

fun main(): Unit = runBlocking {

    val serverJob = CoroutineScope(coroutineContext).launch {
        println("connecting server")
        Servidor.ligar()
    }

    val clientJob = CoroutineScope(coroutineContext).launch {
        println("connecting client")
        Cliente.ligar()
    }

    // 等待两个协程全部执行完成
    serverJob.join()
    clientJob.join()
}

额外优化:调整依赖

桌面平台无需依赖kotlinx-coroutines-android(该依赖为Android平台专用),建议移除该依赖,仅保留核心协程库即可:

org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4

内容的提问来源于stack exchange,提问作者Gilian Marques

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 11:02:08