Kotlin:在不访问 CoroutineScope 的情况下获取当前的 CoroutineContext.Key?

Posted

技术标签:

【中文标题】Kotlin:在不访问 CoroutineScope 的情况下获取当前的 CoroutineContext.Key?【英文标题】:Kotlin: Get Current CoroutineContext.Key without access to the CoroutineScope? 【发布时间】:2019-06-11 14:41:57 【问题描述】:

我正在尝试拦截 System.out 打印语句,并且在多线程程序中,我计划使用 CoroutineContext.Key 作为映射键将它们添加到映射中,因此我知道输出属于哪个协程到。

我正在执行的子方法无权访问CoroutineScope,因为这是在父方法上启动的。

我希望有一个类似于CoroutineContext.currentKey 的静态方法,但这看起来并不存在。

我用他们的Task.CurrentId在 C# 中实现了类似的东西

我有什么办法可以做到这一点吗?

谢谢

【问题讨论】:

CoroutineContext.Key 是一个常数。您需要线程 ID,但您也不想要它,因为您似乎想要识别协程,而协程并不局限于单个线程。 没错。有没有解决的办法?我可以切换到使用 Thread 作为映射键,因为我可以从任何地方调用 Thread.currentThread。但这对性能的影响要大得多! 为什么更重性能? currentThread() 是一个非常便宜的电话。 就像我不得不在一个新线程中交换我的异步代码,而不是一个新的协程? 你说“所以我知道输出属于哪个线程”。但也许你不是这个意思。我没有找到用于协程的明显键。 【参考方案1】:

您可以创建自己的线程局部变量来保留您自己的协程标识符,甚至直接保存它的输出,并使用ThreadLocal.asContextElement() 扩展函数将其转换为协程上下文元素。现在,如果你用这个元素启动你的协程,那么这个线程局部变量的指定值将自动安装到相应的线程局部变量中,因为这个协程从一个线程跳到另一个线程。请看以下示例代码:

import kotlinx.coroutines.*

val myId = ThreadLocal<String>()

// I'm not a suspending function, yet I know what coroutine I work in
fun whereAmI() 
    println("I'm in coroutine '$myId.get()'")


fun main() = runBlocking<Unit> 
    launch(myId.asContextElement("First")) 
        whereAmI()
    
    launch(myId.asContextElement("Second")) 
        whereAmI()
    

【讨论】:

以上是关于Kotlin:在不访问 CoroutineScope 的情况下获取当前的 CoroutineContext.Key?的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin 协程协程启动 ④ ( 协程启动模式 | 协程构建器启动模式参数 | DEFAULT 模式 | ATOMIC 模式 | LAZY 模式 | UNDISPATCHED 模式 )

Kotlin 协程协程启动 ④ ( 协程启动模式 | 协程构建器启动模式参数 | DEFAULT 模式 | ATOMIC 模式 | LAZY 模式 | UNDISPATCHED 模式 )

在不调用属性的情况下获取休眠惰性关系 n+1 - Kotlin

在 Kotlin Native 中,如何在不使用 C 指针的情况下将对象保留在单独的线程中,并从任何其他线程中改变其状态?

为啥 Kotlin 多平台项目的 commonMain 可以访问 kotlin.jvm 包?

从 Swift 访问 Kotlin 标准库