如何使用runBlocking等待CoroutineScope完成

时间:2018-11-13 09:35:59

标签: kotlin kotlin-coroutines

我正在尝试测试一个声明为CoroutineScope的类。该类的某些方法可以在其范围内launch进行作业,我必须从测试方法中断言这些作业的效果。

这是我尝试过的:

import kotlinx.coroutines.*

class Main : CoroutineScope {
    override val coroutineContext get() = Job()

    var value = 0

    fun updateValue() {
        this.launch {
            delay(1000)
            value = 1
        }
    }
}

fun main() {
    val main = Main()
    val mainJob = main.coroutineContext[Job]!!
    main.updateValue()
    runBlocking {
        mainJob.children.forEach { it.join() }
    }
    require(main.value == 1)
}

我期望updateValue()将在coroutineContext中创建根作业的子级。但是事实证明mainJob.children为空,所以我等不及launch的完成,而require语句失败了。

完成这项工作的正确方法是什么?

2 个答案:

答案 0 :(得分:1)

我的代码中的错误很简单:

override val coroutineContext get() = Job()

我不小心留下了一个自定义吸气剂,这意味着对coroutineContext的每次访问都会创建一个新作业。自然,我在测试代码中找到的工作没有孩子。删除get()可使代码起作用:

override val coroutineContext = Job()

答案 1 :(得分:0)

将协程生成器启动修改为

this.launch(start = CoroutineStart.LAZY) 

并将您的工作对象初始化更改为直接

override val coroutineContext : Job =   Job()  

它应该产生预期的结果

这是我尝试的示例,它产生了预期的结果

import kotlinx.coroutines.*
import kotlin.coroutines.CoroutineContext

class Main : CoroutineScope {

val scope: CoroutineScope = this

override val coroutineContext = Job()
    //Dispatchers.Default +

var value = 0

 fun updateValue(csc : CoroutineScope) {
    csc.launch(context = coroutineContext, start = CoroutineStart.LAZY) { println(this.coroutineContext[Job]!!.toString() + " job 2") }
    csc.launch (context = coroutineContext, start = CoroutineStart.LAZY){ println(this.coroutineContext[Job]!!.toString() + " job 3") }
    csc.launch (start = CoroutineStart.LAZY){
        println(this.coroutineContext[Job]!!.toString() + " job 1")
        //delay(1000)
        value = 1
    }

 }

fun something() {
    launch (start = CoroutineStart.LAZY){
        println(this.coroutineContext[Job]!!.toString() + " something 1")
    }

    launch (start = CoroutineStart.LAZY){
        println(this.coroutineContext[Job]!!.toString() + " something 2")
    }

    launch(start = CoroutineStart.LAZY) {
        println(this.coroutineContext[Job]!!.toString() + " something 3")
        delay(2000)
        value = 1
    }
}

}

fun main() {
    val main = Main()
    val mainJob = main.coroutineContext[Job]!!
    main.updateValue(main.scope)
    //main.something()
    runBlocking {
        //println(mainJob.children.count())
        println(mainJob.children.count())
        mainJob.children.forEach {
            //println("in run blocking")
            println(it.toString())
            it.join()
        }
    }
    println(main.value)
}


`