Что делает Coroutine Join? - PullRequest
0 голосов
/ 03 января 2019

Так, например, у меня есть следующий код:

scope.launch {
    val job = launch {
        doSomethingHere()
    }
    job.join()

    callOnlyWhenJobAboveIsDone()
}

Job.join() является таковым в документации:

Приостанавливает сопрограмму, пока эта работа не будет завершена. Этот вызов возобновляется нормально (без исключения), когда задание по какой-либо причине завершено, а задание вызывающей сопрограммы все еще активно. Эта функция также запускает соответствующую сопрограмму, если задание все еще находится в новом состоянии.

Если я правильно понимаю, так как join() приостанавливает сопрограмму до ее завершения, то мой код выше будет делать именно то, что он хочет. То есть метод callOnlyWhenJobAboveIsDone() будет вызываться только после завершения doSomethingHere(). Это правильно?

Может ли кто-нибудь объяснить более подробно сценарий использования job.join()? Заранее спасибо.

Объясняя далее мой случай использования:

val storeJobs = ArrayList<Job>()

fun callThisFunctionMultipleTimes() {
    scope.launch {
        val job = launch {
            doSomethingHere()
        }
        storeJobs.add(job) 
        job.join()

        callOnlyWhenJobAboveIsDone()
    }
}

fun callOnlyWhenJobAboveIsDone() {
    // Check if there is still an active job 
    // by iterating through the storedJobs
    // and checking if any is active
    // if no job is active do some other things
}

это допустимый вариант использования job.join()?

Ответы [ 2 ]

0 голосов
/ 03 января 2019

То есть метод callOnlyWhenJobAboveIsDone () будет вызываться только после завершения doSomethingHere ().Это правильно?

Да.

Может кто-нибудь объяснить дальнейшее использование case для job.join ()?

В вашем случае на самом деле нет необходимости в другой работе, вы можете просто написать:

scope.launch {
    doSomethingHere()
    callOnlyWhenJobAboveIsDone()
}

Это будет делать то же самое, так что на самом деле это не случай использованиядля работы.Теперь есть другие случаи, когда .join() действительно полезен.

1) Вы хотите запустить (запустить) несколько асинхронных действий параллельно и дождаться завершения всех из них:

 someData
   .map { Some.asyncAction(it) } // start in parallel
   .forEach { it.join() } // wait for all of them

2) Вы должны отслеживать асинхронное состояние, например, обновление:

var update = Job()

fun doUpdate() {
   update.cancel() // don't update twice at the same time
   update = launch {
     someAsyncCode()
   }
}

Теперь, чтобы убедиться, что было выполнено последнее обновление, например, если вы хотите использовать некоторые обновленные данные,вы можете просто:

 update.join()

где угодно, вы также можете

 update.cancel()

, если хотите.

Что действительно полезно в launch {}, так это то, что он не тольковозвращает задание, но также прикрепляет задание к CoroutineScope.Благодаря этому вы можете отслеживать все асинхронные действия, происходящие внутри вашего приложения.Например, в вашем пользовательском интерфейсе вы можете заставить каждый элемент расширять CoroutineScope, затем вы можете просто отменить область, если элемент покидает визуализированную область, и все обновления / анимации в нем будут остановлены.

0 голосов
/ 03 января 2019

Котлин Job.join() является неблокирующим эквивалентом Java Thread.join().

Таким образом, ваше предположение верно: смысл job.join() состоит в том, чтобы дождаться завершения получателя job, прежде чем выполнить оставшуюся часть текущей сопрограммы.

Однако вместо того, чтобы блокировать поток, вызывающий join() (как в случае с Thread.join() в Java), он просто приостанавливает сопрограмму, вызывающую join(), оставляя текущий поток свободным, чтобы делать все, что пожелает (например, выполнить другую сопрограмму) тем временем.

...