import kotlinx.coroutines.*
fun main() = runBlocking {
println("Main program starts: ${Thread.currentThread().name}")
withContext(Dispatchers.IO.limitedParallelism(1)) {
println("Switched to limited parallelism context: ${Thread.currentThread().name}")
repeat(2) { i ->
launch {
println("Coroutine $i starts on thread ${Thread.currentThread().name}")
delay(1000L)
}
}
}
println("Main program ends: ${Thread.currentThread().name}")
}
Приведенный выше код Kotlin печатает приведенный ниже результат.
Main program starts: main
Switched to limited parallelism context: DefaultDispatcher-worker-1
Coroutine 0 starts on thread DefaultDispatcher-worker-1
Coroutine 1 starts on thread DefaultDispatcher-worker-1
Main program ends: main
Но если я напишу специальную функцию для withContext(Dispatchers.IO.limitedParallelism(1)), поведение кода внутри withContext изменится.
import kotlinx.coroutines.*
fun main() = runBlocking {
println("Main program starts: ${Thread.currentThread().name}")
atomically {
println("Switched to limited parallelism context: ${Thread.currentThread().name}")
repeat(2) { i ->
launch {
println("Coroutine $i starts on thread ${Thread.currentThread().name}")
delay(1000L)
}
}
}
println("Main program ends: ${Thread.currentThread().name}")
}
internal suspend inline fun <R> atomically(crossinline f: () -> R): R =
withContext(Dispatchers.IO.limitedParallelism(1)) { f() }
Приведенный выше код Kotlin печатает приведенный ниже результат.
Main program starts: main
Switched to limited parallelism context: DefaultDispatcher-worker-1
Coroutine 0 starts on thread main
Coroutine 1 starts on thread main
Main program ends: main
Как вы можете видеть, сопрограмма с двумя дочерними элементами внутри withContext не запускается в DefaultDispatcher, вместо этого она выполняется в main. Я хотел бы понять, почему происходит такое изменение поведения.
@broot Спасибо за замечание, иногда бывает сложно найти повторяющийся вопрос. Я проголосовал за ваш ответ.





Извините, что не могу написать подробный ответ прямо сейчас (по телефону), но я почти уверен, что ваша проблема связана с тем, что параметр функции f в вашей извлеченной функции не имеет CoroutineScope получателя. Таким образом, запуск вложенных сопрограмм будет выполняться не в дочерней области withContext, а в области сопрограммы на один уровень выше.
Он может сильно отличаться от вопроса, на который я указал, помеченный как дубликат. Но если присмотреться, то это точно тот же самый случай. Он даже создает функцию полезности для
withContext, и они допустили ту же ошибку, что и вы.