Как работает асинхронное распространение исключений?Android

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Как работает асинхронное распространение исключений?

Сообщение Anonymous »

Я читал во многих местах, что async может проглатывать исключения, если мы не вызываем await, но, насколько я вижу, он почти всегда выдает их независимо от того, используется await или нет.
Например, здесь я бы предположил, что уже слишком поздно перехватывать исключения, поскольку оно уже распространилось, поэтому происходит сбой

Код: Выделить всё

lifecycleScope.launch {
val job = async {
throw Exception()
}

try {
job.await()
} catch (e: Exception) {
println("caught")
}
}
Но в аналогичном сценарии я бы предположил, что он должен распространиться на внешний асинхронный интерфейс, но блок catch запускается и сбоя не происходит:

Код: Выделить всё

val scope = CoroutineScope(Job())
scope.async {
val job = async {
throw Exception()
}

try {
job.await()
} catch (e: Exception) {
println("caught")
}
}
Но здесь async действительно может сохранить его и перехватить позже:

Код: Выделить всё

val job = lifecycleScope.async {
launch {
throw Exception()
}
}

runBlocking {
try {
job.await()
} catch (e: Exception) {
println("caught")
}
}
Здесь я предполагаю, что блоки async и запуска выполняются параллельно, и try-catch должен иметь возможность наблюдать и перехватывать исключение, но оно выходит из строя:

Код: Выделить всё

runBlocking {
async {
val job = async {
throw Exception()
}
launch {
try {
job.await()
} catch (e: Exception) {
println("caught")
}
}
}
}
Тем не менее, если я удалю ожидание при запуске, оно снова заработает:

Код: Выделить всё

lifecycleScope.async {
val job = async {
throw Exception()
}

try {
job.await()
} catch (e: Exception) {
println("caught")
}
}
Иногда блок catch действительно запускается, но все равно выходит из строя, независимо от того, нарушаю я структурированный параллелизм или нет:

Код: Выделить всё

val scope = CoroutineScope(Job())
scope.async {
val job = async {
throw Exception()
}

try {
job.await()
} catch (e: Exception) {
println("caught")
}
}
У меня было предположение, что это зависит от обработчика исключений во время выполнения, основываясь на этом: https://stackoverflow.com/a/60078180/10698676, но большинство описанных выше сбоев происходит независимо от того, работаю ли я на Android или JVM.
Мое другое предположение заключалось в том, что, возможно, это зависит от потока, поскольку иногда исключение просто регистрируется, поэтому я предположил, что, возможно, он аварийно завершает работу только при Основной поток, но не на IO/Default, но не имело значения, какой диспетчер я использовал, результаты были одинаковыми.
Я пробовал много других вариантов, но не смог понять принцип
Так как же это работает? Чего мне не хватает?

Подробнее здесь: https://stackoverflow.com/questions/798 ... ally-works
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»