2

Where is task to process big list of items in sequential-parallel way: split big list to chunks, process chunks one after another, process items from each chunk in parallel. Implementing this task, I encounter a problem and reduce that task to reproduce it in simplest way.

val rootScope = CoroutineScope(Dispatchers.IO)

val list: List<Int> = listOf(1,2,3,4,5)

rootScope.launch {
    val rootLocalScope = this
    log("-----> rootScope (start)")

    launch {
        val mediumLocalScope = this

        list.map {  i ->
            // 
            // Replace rootLocalScope to mediumLocalScope in SupervisorJob() and hangs up work...
            //
            launch (SupervisorJob(rootLocalScope.coroutineContext.job)) {
                log("Downloading file-$i")
                delay(1000)
            }
        }.joinAll()
        
    }.join()

    log("-----> rootScope (finish)")
}

Remark: all .join() are required, there is no right sequence of work without it.

Output is:

With SupervisorJob(rootLocalScope.coroutineContext.job):

========= work() ========
-----> rootScope (start)
Downloading file-1
Downloading file-2
Downloading file-3
Downloading file-4
Downloading file-5
-----> rootScope (finish)

With SupervisorJob(mediumLocalScope.coroutineContext.job):

========= work() ========
-----> rootScope (start)
Downloading file-1
Downloading file-2
Downloading file-3
Downloading file-4
Downloading file-5
*I.e. top level coroutine not reached its finish...*

So, the question: why SupervisorJob(mediumLocalScope.coroutineContext.job) not works?

1
  • 2
    I think I understand the reason for the behavior, but I feel the real answer should be: remove all "strange" code bits, remove 60% of the code and keep it simple. You pass a Job to launch, which in most cases is not a very good idea and it may result with many kinds of strange behaviors. You do a lot of launches and joins and they all look unnecessary. You wrote a "strange" code, so you got a "strange" behavior. Is there any specific reason for doing the above? Couldn't you simply do: list.map { launch { ... }}.joinAll() and that's it? Commented Jan 23 at 1:15

1 Answer 1

0

I found on StackOverflow similar theme. Shortly: you shoud manually call .complete() on intermediate job (SupervisorJob in discussed case, but simple Job behaves the same) after .joinAll() child jobs.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.