#kotlin #exit #kotlin-coroutines
#kotlin #выход #kotlin-сопрограммы
Вопрос:
Я пытаюсь заставить свой код выйти из программы, когда что-то происходит, например, команда выхода пользователя. Вот как я запускаю свою программу:
fun main() = runBlocking {
Bot().start()
}
К сожалению, запуск exitProcess(0)
or Thread.currentThread().interrupt()
, похоже, ничего не делает при вызове вне start()
, что действительно неудобно в моем случае использования.
Есть ли какой-либо способ обойти это?
Комментарии:
1. Как
start()
выглядит?
Ответ №1:
runBlocking {
val job = launch { start() }
// Process input via other APIs here. When done:
job.cancel()
}
(Возможно, вы захотите изучить каналы для доставки Cmd
объектов в свой командный цикл и просто закрыть канал, когда ввод будет выполнен.)
Комментарии:
1. К сожалению, это, похоже, не работает. У меня есть это
2. отмена() приведет к тому, что следующая точка приостановки в start() вызовет исключение CancellationException. Если start() уже завершен или застрял в блокировке ввода-вывода, cancel() ничего не сделает.
3.
start()
не имеет точек приостановки, она завершается, поскольку это начальная последовательность. Сможет ли использованиеdelay(largeNumber)
или какого-либо бесконечного цикла while обойти это?4. Мне нужно было позвонить
exitProcess(0)
после отмены задания из другого процесса, спасибо
Ответ №2:
Я столкнулся с такой же проблемой с runBlocking
.
Немного предыстории: Прежде всего, мы должны были использовать runBlocking
, чтобы преодолеть разрыв между реализацией интерфейса библиотечного метода и компонентом нашего приложения, доступ к которому возможен только в ОСНОВНОМ потоке / UI. Внутри реализации этого метода нам пришлось синхронно возвращать значение, нам пришлось переключить наш контекст с фонового потока на поток пользовательского интерфейса, чтобы явно получить эту информацию в потоке пользовательского интерфейса. Мы никогда не выбирали использовать runBlocking
, но нам пришлось, поскольку другого пути не было.
Проблема: это runBlocking
блокировало другой фоновый поток (в определенной ситуации). Это никогда не заканчивалось, и это заблокировало фоновый поток, который выполнялся в отдельном дочернем процессе нашего приложения. Итак, я искал решение и обнаружил, что ниже сообщается о проблеме на Github.
Согласно ответу в сообщаемой проблеме здесь
Когда
runBlocking
механизм обнаруживает, что он отменен, он не должен завершать цикл событий до тех пор, пока сопрограмма внутри него все еще
активна.
Затем он далее объясняет, что
Таким образом, завершение сопрограммы обрабатывается в цикле выполнения событий, и цикл событий завершается после этого.
Решение: Итак, я придумал это решение, которое сработало для меня, упомянутое ниже, вы можете использовать эту функцию более высокого порядка. Это 100% рабочее решение, протестированное и проверенное на производстве. ПРИМЕЧАНИЕ: Пожалуйста, не используйте withContext()
вместо async()
во фрагменте кода ниже, так как это никогда не сработает.
fun <T> runBlockingWithTimeout(
lifecycleScope: LifecycleCoroutineScope?,
timeoutMillis: Long = 500L,
block: () -> T
): T? {
return lifecycleScope?.let {
runBlocking {
withTimeoutOrNull(timeMillis = timeoutMillis) {
async(lifecycleScope.coroutineContext) {
block.invoke()
}.await()
}
}
}
}