HCRM博客

为什么在使用invokeblocking时会出现报错?

在Kotlin中,CoroutineScope 提供了一种方便的方式来管理协程的生命周期,当你在一个协程作用域中启动一个新的协程时,这个新的协程会在该作用域结束时自动取消,在某些情况下,你可能需要从非协程环境(如普通的函数或回调)中启动一个阻塞的协程,这时可以使用launch 函数配合Dispatchers.IO 来避免主线程被阻塞。

1. 使用GlobalScope.launch

GlobalScope 是一个全局的协程作用域,它永远不会被取消,这意味着你可以在任何地方启动一个协程,而不用担心作用域的生命周期问题,由于GlobalScope 是全局性的,它可能会引起内存泄漏,特别是在长时间运行的应用中,你应该尽量避免使用GlobalScope,除非你有明确的理由。

import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.Dispatchers
fun main() {
    GlobalScope.launch(Dispatchers.IO) {
        // 在这里执行你的耗时操作
    }
}

2. 使用runBlocking

如果你需要在当前的线程中等待协程完成,你可以使用runBlocking 函数,这会阻塞当前线程,直到协程完成,这种方法通常用于测试或在主函数中启动协程。

import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.Dispatchers
fun main() = runBlocking {
    launch(Dispatchers.IO) {
        // 在这里执行你的耗时操作
    }
}

3. 使用withContext

如果你需要在当前协程中切换到不同的调度器,你可以使用withContext 函数,这不会阻塞当前线程,而是将协程挂起,直到新的调度器上的操作完成。

import kotlinx.coroutines.withContext
import kotlinx.coroutines.Dispatchers
suspend fun main() {
    withContext(Dispatchers.IO) {
        // 在这里执行你的耗时操作
    }
}

4. 使用asyncawait

如果你需要并发地执行多个任务,并且需要它们的结果,你可以使用asyncawait 函数。async 函数会启动一个新的协程,并立即返回一个Deferred 对象,你可以使用await 函数来等待这个Deferred 对象的结果,而不阻塞当前线程。

import kotlinx.coroutines.async
import kotlinx.coroutines.await
import kotlinx.coroutines.Dispatchers
suspend fun main() {
    val result = async(Dispatchers.IO) {
        // 在这里执行你的耗时操作,并返回结果
    }
    val resultValue = result.await() // 等待结果,但不阻塞当前线程
}

5. 使用CoroutineScopeJob

如果你需要更细粒度的控制协程的生命周期,你可以创建一个自定义的CoroutineScope,你可以使用SupervisorJob 来确保子协程在父协程取消时不会被取消。

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
import kotlinx.coroutines.Dispatchers
fun main() {
    val scope = CoroutineScope(SupervisorJob())
    scope.launch(Dispatchers.IO) {
        // 在这里执行你的耗时操作
    }
}

6. 使用ensureActive

如果你需要在协程中检查它是否仍然活跃,你可以使用ensureActive 函数,如果协程已经被取消,它会抛出CancellationException

import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.Dispatchers
suspend fun main() {
    launch(Dispatchers.IO) {
        ensureActive() // 检查协程是否仍然活跃
        // 在这里执行你的耗时操作
    }
}

7. 使用joinJob

如果你需要等待一个协程完成,并且不需要它的结果,你可以使用joinJob 函数,这会阻塞当前线程,直到协程完成。

import kotlinx.coroutines.joinJob
import kotlinx.coroutines.launch
import kotlinx.coroutines.Dispatchers
fun main() {
    val job = launch(Dispatchers.IO) {
        // 在这里执行你的耗时操作
    }
    job.joinJob() // 等待协程完成
}

8. 使用cancelAndJoin

如果你需要取消一个协程,并等待它完成,你可以使用cancelAndJoin 函数,这会取消协程,并等待它完成。

import kotlinx.coroutines.cancelAndJoin
import kotlinx.coroutines.launch
import kotlinx.coroutines.Dispatchers
fun main() {
    val job = launch(Dispatchers.IO) {
        // 在这里执行你的耗时操作
    }
    job.cancelAndJoin() // 取消协程并等待它完成
}

9. 使用isActive

如果你需要检查一个协程是否仍然活跃,你可以使用isActive 属性,如果协程已经被取消,它会返回false

import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.Dispatchers
suspend fun main() {
    val job = launch(Dispatchers.IO) {
        if (isActive) {
            // 在这里执行你的耗时操作
        } else {
            // 协程已经被取消
        s}
    }
}

10. 使用delay

如果你需要在协程中延迟一段时间,你可以使用delay 函数,这会挂起协程,直到指定的时间过去。

import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.Dispatchers
suspend fun main() {
    launch(Dispatchers.IO) {
        delay(1000L) // 延迟1秒
        // 在这里执行你的耗时操作
    }
}

11. 使用withTimeout

如果你需要在协程中设置一个超时时间,你可以使用withTimeout 函数,如果超时时间到了,它会取消协程,并抛出TimeoutCancellationException

import kotlinx.coroutines.withTimeout
import kotlinx.coroutines.launch
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.TimeoutCancellationException
suspend fun main() {
    try {
        withTimeout(1000L) { // 设置超时时间为1秒
            launch(Dispatchers.IO) {
                // 在这里执行你的耗时操作
            }
        }
    } catch (e: TimeoutCancellationException) {
        // 处理超时异常
    }
}

12. 使用onJoinonCompleted

如果你需要在协程完成时执行一些操作,你可以使用onJoinonCompleted 函数,这些函数会在协程完成时被调用。

import kotlinx.coroutines.onJoin
import kotlinx.coroutines.onCompleted
import kotlinx.coroutines.launch
import kotlinx.coroutines.Dispatchers
suspend fun main() {
    val job = launch(Dispatchers.IO) {
        // 在这里执行你的耗时操作
    }
    job.onJoin {
        // 在这里执行你的操作,当协程完成时会被调用
    }
    job.onCompleted {
        // 在这里执行你的操作,当协程完成时会被调用,无论它是正常完成还是异常完成
    }
}
分享:
扫描分享到社交APP
上一篇
下一篇