Асинхронизация слушателей события запуска с Kotlin Coroutines - PullRequest
0 голосов
/ 02 декабря 2018

Я создал абстрактный класс 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 голосов
/ 02 декабря 2018

Вы запускаете прослушиватели событий с GlobalScope.launch(), который не взаимодействует с окружающей областью runBlocking().Означает runBlocking() возврат до завершения всех запущенных сопрограмм.Вот почему вы не видите результат.

Кстати: использование сопрограмм и runBlocking не рекомендуется

Вы должны добавить suspend к функции emit().То же самое верно для параметра handler - сделайте его приостановленным.

...