Как получить имя сопрограммы в Котлине?

Меня интересует внутренняя работа сопрограммы при suspended в основном потоке. Настоящий вопрос заключается в том, как зарегистрировать функцию suspended, которая является сопрограммой в основном потоке. Где именно происходит казнь? Это виртуальный поток?

19
0
7 609
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Если вы говорите о регистрации имени сопрограммы:

Вы можете достичь этого,

  1. Дайте имя сопрограмме (если вы хотите собственное имя): launch(CoroutineName("My-Coroutine"))

  2. Включите ведение журнала в меню панели инструментов IntelliJ: «Выполнить» -> «Редактировать конфигурацию» и добавьте

-Dkotlinx.coroutines.debug в настройках ВМ.

VM Option in Edit Configuration

Тогда вы можете увидеть @My-Coroutine в logcat.

Попробуйте код ниже после изменения конфигурации редактирования:

fun main() = runBlocking {
println("   'runBlocking': I'm working in thread ${Thread.currentThread().name}")

val job = launch(CoroutineName("my-custom-name")) {
    println("   'runBlocking': I'm working in thread ${Thread.currentThread().name}")

}

job.join()}

Результат: Result

Как сделать то же самое для мультиплатформы и/или Native?

Myroslav 22.02.2020 11:04

Где варианты ВМ? Я использовал Android Studio 4.1.1 и в конфигурации «Выполнить/Редактировать»... нашел только VmOptions в шаблонах/kotlin. Это то же самое, что вы имеете в виду?

Reyhane Farshbaf 06.01.2021 07:37

Похоже, это все еще не поддерживается в Android Studio.

tyler 09.09.2021 20:27

Вы можете дать имя сопрограмме, используя метод CoroutineName(name:String) во время создания сопрограммы:

repeat(5) {
            GlobalScope.launch(CoroutineName("$it")) {
                displayGreetingsFor(it)
            }
        }

Чтобы получить имя, данное сопрограмме, используйте coroutineContext[CoroutineName.Key], как показано ниже:

private suspend fun displayGreetingsFor(i: Int) {
        delay(100)
        println(
            " ${coroutineContext[CoroutineName.Key]} is executing on thread : ${Thread.currentThread().name}"
        )
    }

Это будет печатать следующие o/p на консоли:

CoroutineName(0) is executing on thread : DefaultDispatcher-worker-3
CoroutineName(1) is executing on thread : DefaultDispatcher-worker-2
CoroutineName(2) is executing on thread : DefaultDispatcher-worker-8
CoroutineName(3) is executing on thread : DefaultDispatcher-worker-6
CoroutineName(4) is executing on thread : DefaultDispatcher-worker-5

Другие ответы не отвечают на вопрос напрямую «Как получить имя сопрограммы в Котлине?»; вместо этого они предлагают, как назвать сопрограмму.

Если внутри сопрограммы, имя можно получить с помощью currentCoroutineContext()[CoroutineName].

Если вне сопрограммы, нет прямого способа получить имя, используя ссылку на Job или Deferred (очень плохо). Тем не менее, есть хак отражения, который можно использовать. Конечно, прилагаются обычные предупреждения, а именно: отсутствие безопасности типов и взлом внутренних API, которые могут измениться в любое время.

@Suppress("UNCHECKED_CAST")
val nameString = AbstractCoroutine::class.memberFunctions
    .single { it.name == "nameString" } as Function1<AbstractCoroutine<*>, String>
val name = nameString(job as AbstractCoroutine<*>)
    .replace("\"", "")
    .takeWhile { it != '#' }

Метод/функция, содержащие этот код, должны быть помечены @InternalCoroutinesApi.

Другие вопросы по теме