Когда следует использовать coroutineScope против supervisorScope? - PullRequest
0 голосов
/ 02 декабря 2018

Может кто-нибудь объяснить, в чем именно разница между этими двумя?

Когда вы используете один над другим?

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 02 декабря 2018

Лучший способ объяснить разницу - это объяснить механизм coroutineScope.Рассмотрим этот код:

suspend fun main() = println(compute())

suspend fun compute(): String = coroutineScope {
    val color = async { delay(60_000); "purple" }
    val height = async<Double> { delay(100); throw HttpException() }
    "A %s box %.1f inches tall".format(color.await(), height.await())
}

compute() извлекает из сети две вещи и объединяет их в описание строки.В этом случае первая выборка занимает много времени, но в итоге получается успешной;второй сбой почти сразу после 100 миллисекунд.

Какое поведение вы хотели бы для приведенного выше кода?

  1. Хотели бы вы на минутку color.await() только для того, чтобы понять, что другой сетевой вызов давно потерпел неудачу?

  2. Или, возможно, выХотели бы вы, чтобы функция compute() поняла через 100 мс, что один из ее сетевых вызовов завершился неудачно и сразу же завершился ошибкой?

С supervisorScope вы получаете 1., сcoroutineScope вы получаете 2.

Поведение 2. означает, что, хотя async само по себе не выбрасывает исключение (оно просто завершает Deferred, которое вы получили от него),сбой немедленно отменяет его сопрограмму, которая отменяет родительский элемент, который затем отменяет все остальные дочерние элементы.

Такое поведение может быть странным, когда вы об этом не знаете.Если вы поймаете исключение из await(), вы будете думать, что восстановились после него, но не сделали этого.Весь объем сопрограмм все еще отменяется.В некоторых случаях есть законная причина, по которой вы этого не хотите: именно тогда вы будете использовать supervisorScope.

0 голосов
/ 02 декабря 2018

Я думаю Роман Елизаров объясняет это довольно подробно , но для краткости:

У вас есть такая иерархия:

  • Родительская сопрограмма
    • Детская сопрограмма 1
    • Детская сопрограмма 2
    • ...
    • Детская сопрограмма N

Предположим, что «Coroutine I» не удается.Что вы хотите, чтобы произошло с его родителем?

Если вы хотите, чтобы его родитель также потерпел неудачу, используйте coroutineScope.Вот что такое структурированный параллелизм.

Но если вы не хотите, чтобы он завершился неудачей, например, child был какой-то фоновой задачей, которую можно запустить снова, используйте supervisorScope.

...