Создает ли withContext новую сопрограмму? - PullRequest
1 голос
/ 26 февраля 2020

У меня есть следующий код:

import kotlinx.coroutines.*

fun main() = runBlocking {
    launch {
        println("in sub coroutine ${Thread.currentThread().name}")
    }
    println("before coroutine in main ${Thread.currentThread().name}")
    withContext(Dispatchers.IO) {
        println("hello from coroutine ${Thread.currentThread().name}")
        delay(1500)
        println("hello from coutoutine after delay ${Thread.currentThread().name}")
    }
    println("after coroutine in main ${Thread.currentThread().name}")
}

Вывод:

before coroutine in main main @coroutine#1
hello from coroutine DefaultDispatcher-worker-1 @coroutine#1
in sub coroutine main @coroutine#2
hello from coutoutine after delay DefaultDispatcher-worker-1 @coroutine#1
after coroutine in main main @coroutine#1

Насколько я понимаю, withContext переключает код в новый контекст, где код выполняется в другой поток, и текущая сопрограмма приостанавливается до завершения кода в новом потоке. Но оригинальное определение ничего не говорит о создании новой сопрограммы.

Исходное определение из kotlin .github.io:

Вызывает указанную приостановку блок с заданным контекстом сопрограммы, приостанавливается до его завершения и возвращает результат.

Ответы [ 2 ]

4 голосов
/ 26 февраля 2020

Нет взаимно однозначного соответствия между потоками и сопрограммами. Когда сопрограмма возобновляется из приостановки, она может возобновиться в каком-то другом потоке, в зависимости от того, что ему дает Диспетчер.

launch и async создают новые сопрограммы. withContext не создает новую сопрограмму, она только сдвигает контекст существующей сопрограммы, поэтому это функция приостановки (в отличие от launch и async).

1 голос
/ 26 февраля 2020

Я полагаю, что вы просто неправильно читаете свой вывод.

before coroutine in main main @coroutine#1
hello from coroutine DefaultDispatcher-worker-1 @coroutine#1
in sub coroutine main @coroutine#2
hello from coutoutine after delay DefaultDispatcher-worker-1 @coroutine#1
after coroutine in main main @coroutine#1

В этом выводе у вас есть 2 сопрограммы:

  • @ coroutine # 1 (через "runBlocking")
  • @ coroutine # 2 (через «запуск»)

и два потока:

  • main
  • DefaultDispatcher-worker-1

Никаких дополнительных сопрограмм не создается при выполнении «withContext». Ваши две сопрограммы - "runBlocking" и "launch".

...