Невозможно запустить сопрограмму в сыром потоке.По крайней мере, вы должны превратить существующий поток в тот, который вращает цикл событий верхнего уровня.Это достигается с помощью вызова runBlocking
в самом верху стека вызовов потока (т. Е. Внутри его метода run()
).
В потоке графического интерфейса или любом другом виде потока, который выполняет цикл обработки событий.вам нужен соответствующий Dispatcher
, который передает сопрограммы в этот цикл событий.Kotlin уже предоставляет диспетчеры для Swing, JavaFX, Android и т. Д. В этих случаях вам необходимо launch
сопрограмма из какого-либо существующего обработчика событий GUI, например:
myScope.launch {
val player = test()
... use the player ...
}
myScope
должен быть объектом, которыйCoroutineScope
реализует что-то вроде этого:
override val coroutineContext = Dispatchers.Main + SupervisorJob()
Это даст вам возможность полностью отменить все сопрограммы, работающие в той же области, вызывая
coroutineContext[Job]!!.cancel()
Мой пример используетдиспетчер Main
, который преобразуется в поток GUI при импорте библиотеки сопрограмм Kotlin, соответствующей вашей структуре пользовательского интерфейса.
Функция test()
должна стать suspend fun
, которая временно переключает диспетчер в пул потоковдля блокировки операций.Вот как может выглядеть базовый пример:
suspend fun test() = withContext(Dispatchers.IO) {
MainActivity.database?.playerDao()!!.loadPlayer()
}
Наконец, обратите внимание, я не упоминаю async
вообще в этом ответе.async
Kotlin имеет очень конкретное назначение, это не общее средство, как на других языках.Его цель - строго параллельная декомпозиция, где вы разбиваете одну задачу на несколько параллельных подзадач.