触发事件监听器与Kotlin Coroutines异步

时间:2018-12-02 19:11:26

标签: kotlin kotlinx.coroutines

我创建了一个抽象的Event类,该类用于在Kotlin中创建事件。现在,我想使用协同程序异步调用每个用户。

abstract class Event<T> {
    private var handlers = listOf<(T) -> Unit>()

    infix fun on(handler: (T) -> Unit) {
        handlers += handler
        println(handlers.count())
    }

    fun emit(event: T) =
        runBlocking {
            handlers.forEach { subscriber ->
                GlobalScope.launch {
                    subscriber(event)
                }
            }
        }
}

还有一个可用于创建事件侦听器和事件发布者的具体类

class AsyncEventTest {
    companion object : Event<AsyncEventTest>()

    fun emit() = emit(this)
}

问题是,当我运行以下代码时,我可以看到它创建了所有侦听器,但没有执行一半。

fun main(args: Array<String>) {
    val random = Random(1000)

    runBlocking {
        // Create a 1000 event listeners with a random delay of 0 - 1000 ms
        for (i in 1..1000)
            AsyncEventTest on {
                GlobalScope.launch {
                    delay(random.nextLong())
                    println(i)
                }
            }
    }

    println("================")

    runBlocking {
        // Trigger the event
        AsyncEventTest().emit()
    }
}

我在这里想念什么?

更新

删除delay(random.nextLong()时,将执行所有处理程序。这很奇怪,因为我试图以这种方式模拟处理程序的不同响应时间,并且我认为处理程序应始终执行或引发异常。

1 个答案:

答案 0 :(得分:0)

您正在使用GlobalScope.launch()运行事件监听器,该事件监听器与周围的runBlocking()作用域不交互。意味着runBlocking()在所有启动的协同程序完成之前返回。这就是您看不到输出的原因。

顺便说一句:不建议您使用协程和runBlocking

您应将suspend添加到emit()函数中。 handler参数也是如此-使其可挂起。