假设我提供了一个函数,比如runByChannel,我打算将一个lambda发送到一个通道以供执行,然后使用CompletableDefined来接收结果.我需要避免的一个场景是在runByChannel执行的lambda中再次调用runByChannel.这可能导致僵局.

在非协程环境中,您可以使用ThreadLocal变量来设计一个标志,指示函数是否已经进入当前线程.您每次进入时都会判断这面旗帜.然而,在协程环境中,线程调度不是固定的,所以我认为ThreadLocal没有什么用处.有没有更好的办法?注意,我不能设计参数链来表示条目的数量,因为runByChannel将在中间调用其他函数,并且该参数不能连续向下传递.

推荐答案

当然. ThreadLocal对于协程来说几乎从来没有用过,但是CoroutineContext可以完成任务;它通过协程调用和启动自动向下递归传递.

object Recursive: CoroutineContext.Element, CoroutineContext.Key<Recursive> {
  override val key: CoroutineContext.Key<Recursive> get() = this
}

suspend fun cantCallMeRecursively(lambda: suspend () -> Unit) {
  require(currentCoroutineContext()[Recursive] == null) { "recursively called" }
  withContext(Recursive) { lambda() }
}

Kotlin相关问答推荐

解决Microronaut中多个可能的Bean候选者冲突

Microronaut Data 4和JDbi

Kotlin中一个接口的实现问题

用vararg替换列表的设计弃用警告

用于将 0.5 变为 0 的 round() 函数的模拟

Flow.state In() 未从其来源接收新值

Kotlin 可空泛型

在 Kotlin 协程中切换 IO 和 UI 的正确方法是什么?

正则表达式 FindAll 不打印结果 Kotlin

如何使用 Hilt 注入应用程序:ViewModel 中的上下文?

将 jetpack compose 添加到现有元素

Android Studio 将 Java 转换为 Kotlin 错误无法推断此参数的类型

Kotlin 的 Double.toInt() 中使用了哪种方法,舍入还是截断?

如何为kotlin异常生成SerialVersionId?

Kotlin的BiMap/2-way hashmap

生成Kotlin类图

用于代码生成的ANTLR工具版本4.7.1与当前运行时版本4.5.3不匹配

使用 rxbinding 时我应该取消订阅吗?

在Kotlin中创建通用二维数组

Android room DAO 接口不适用于继承