如何在Kotlin中获得协程的名称?

Sha*_*ian 3 android coroutine kotlin

我对协程suspended在主线程上的内部工作感到好奇。真正的问题是如何suspended在主线程上记录作为协程的函数。究竟在哪里执行死刑?它是虚拟线程吗?

Abh*_*kar 11

其他答案没有直接回答问题“ How to get the name of a coroutine in Kotlin? ”;相反,他们建议如何命名协程。

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

Job如果在协程之外,则没有直接方法使用对or的引用来检索名称Deferred(太糟糕了)。然而,有一个可以使用的反射技巧。当然,常见的警告也随之而来,即没有类型安全性以及对可能随时更改的内部 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 != '#' }
Run Code Online (Sandbox Code Playgroud)

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


ama*_*pid 6

如果您正在谈论记录协程名称:

您可以通过实现

  1. 给协程命名(如果需要自定义名称): launch(CoroutineName("My-Coroutine"))

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

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

编辑配置中的VM选项

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

在修改配置后尝试以下代码:

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()}
Run Code Online (Sandbox Code Playgroud)

结果: 结果


shi*_*vam 5

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

repeat(5) {
            GlobalScope.launch(CoroutineName("$it")) {
                displayGreetingsFor(it)
            }
        }
Run Code Online (Sandbox Code Playgroud)

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

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

这将在控制台上打印以下 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
Run Code Online (Sandbox Code Playgroud)


eri*_*icn 5

你可以CoroutineName("some name")像其他人提到的那样使用

打印CoroutineName有3种方式:

方法A

System.setProperty("kotlinx.coroutines.debug", "on" )将使 Job.toString() 包含名称

例如

"my coroutine#4":StandaloneCoroutine{Active}@b735e2c
Run Code Online (Sandbox Code Playgroud)

方法B

在每个范围内,打印 CoroutineContext.toString() 将包含名称

例如

CoroutineContext: [CoroutineName(my coroutine), StandaloneCoroutine{Active}@b735e2c, DefaultDispatcher]
Run Code Online (Sandbox Code Playgroud)

方法C

与方法 B 非常相似,对于 Job 对象,我们可以打印(Job as CoroutineScope).coroutineContext

请注意(Job as CoroutineContext)不起作用!(不知道为什么但(Job as CoroutineContext).get[CoroutineName]返回 null)