【问题标题】:How to get the name of a coroutine in Kotlin?如何在 Kotlin 中获取协程的名称?
【发布时间】:2019-06-16 14:29:43
【问题描述】:

suspended 在主线程上时,我很好奇协程的内部工作。真正的问题是如何记录一个suspended 函数,它是主线程上的协程。执行的具体地点在哪里?是虚拟线程吗?

【问题讨论】:

    标签: android kotlin coroutine


    【解决方案1】:

    如果你说的是记录协程名称:

    你可以通过

    来实现
    1. 为协程命名(如果您想要自定义名称):launch(CoroutineName("My-Coroutine"))

    2. 在 IntelliJ 工具栏菜单中启用日志记录:运行 -> 编辑配置并添加

    -Dkotlinx.coroutines.debug 在 VM 选项中。

    然后就可以在logcat中看到@My-Coroutine了。

    编辑配置更改后尝试以下代码:

    fun main() = runBlocking {
    println("   'runBlocking': I'm working in thread ${Thread.currentThread().name}")
    
    val job = launch(CoroutineName("my-custom-name")) {
        println("   'runBlocking': I'm working in thread ${Thread.currentThread().name}")
    
    }
    
    job.join()}
    

    结果:

    【讨论】:

    • 如何为多平台和/或 Native 做同样的事情?
    • 虚拟机选项在哪里?我使用了 Android Studio 4.1.1 并在运行/编辑配置中..仅在模板/kotlin 中找到了 VmOptions。你的意思是一样的吗?
    • Android Studio 似乎仍然不支持此功能
    【解决方案2】:

    您可以在创建协程时使用CoroutineName(name:String) 方法为协程命名:

    repeat(5) {
                GlobalScope.launch(CoroutineName("$it")) {
                    displayGreetingsFor(it)
                }
            }
    

    要检索协程的名称,请使用coroutineContext[CoroutineName.Key],如下所示:

    private suspend fun displayGreetingsFor(i: Int) {
            delay(100)
            println(
                " ${coroutineContext[CoroutineName.Key]} is executing on thread : ${Thread.currentThread().name}"
            )
        }
    

    这将在控制台上打印以下 o/p:

    CoroutineName(0) is executing on thread : DefaultDispatcher-worker-3
    CoroutineName(1) is executing on thread : DefaultDispatcher-worker-2
    CoroutineName(2) is executing on thread : DefaultDispatcher-worker-8
    CoroutineName(3) is executing on thread : DefaultDispatcher-worker-6
    CoroutineName(4) is executing on thread : DefaultDispatcher-worker-5
    

    【讨论】:

      【解决方案3】:

      其他答案没有直接回答问题“如何在 Kotlin 中获取协程的名称?”;相反,他们建议如何命名协程。

      如果在协程中,可以使用currentCoroutineContext()[CoroutineName] 检索名称。

      如果在协程之外,则没有直接的方法可以使用对 JobDeferred 的引用来检索名称(太糟糕了)。但是,有一个可以使用的反射技巧。当然,还会附上通常的警告,即没有类型安全性和入侵可能随时更改的内部 API。

      @Suppress("UNCHECKED_CAST")
      val nameString = AbstractCoroutine::class.memberFunctions
          .single { it.name == "nameString" } as Function1<AbstractCoroutine<*>, String>
      val name = nameString(job as AbstractCoroutine<*>)
          .replace("\"", "")
          .takeWhile { it != '#' }
      

      包含此代码的方法/函数必须标有@InternalCoroutinesApi

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-02-01
        • 2021-03-16
        • 2015-09-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多