noticed strange behavior, not sure if it using coroutineScope incorrectly

37 Views Asked by At

Having a list of the data processors. Each data processor has its own dpProcess() which returns true if the process successfully done.

all of the processor.dpProcess() run in parallel with others (via the launch builder).

but only after all data porcessors are completed then the final onAllDataProcessed() should be called. This is achived by the coroutineScope {} block.

and also the coroutineScope {} block is controled by the withTimeoutOrNull(2000), so that if the processing of data is not completed in 2 sec then will abort it

    suspend fun processData(): Boolean {
        var allDone = dataProcesserList.size > 0
        val result = withTimeoutOrNull(2000) {  // should timeout at 2000
            coroutineScope {  // block the execution sequence until all sub coroutines are completes
                for (processor in dataProcesserList) {
                    launch { // launch each individual process in parallel
                        allDone = allDone && processor.dpProcess()  // update the global final allDone,   if anyone returns false it should be return false 
                    }
                }
            }
        }

        /**
         * strange:  one of the processor.dpProcess() has return false,  but the allDone at here still shows true (and it is not timed out)
         */

        if (result != null && allDone) { // not timeout and all process completed successfully
            onAllDataProcessed()
        } else {
            allDone = false  // timeout or some process failed
        }
        return allDone
    }

Noticed a strange behavior and happens more on device of Android 7.1.1 device than others

Some time the final allDone is true even one of the processor.dpProcess() returns false and not timed out. But same case sometime returns false as expected

Is it because that how it is coded which brings this behavior?

What is better way to put a few functions to run in parallel and wait until all of them are done then advanced to next step. And the whole process should timeout and abort

1

There are 1 best solutions below

0
On

the

launch { // launch each individual process in parallel
                        allDone = allDone && processor.dpProcess()  // update the global final allDone,   if anyone returns false it should be return false 
                    }

is the problem that launch actually could considered to run the block in different thread, so there is concurrence accessing the global allDone, one may have read it before other update it.