James Eschner
11/14/2022, 4:09 PMCoroutineStart.LAZY
. It appears, that if I don’t cancel or await a response, the runBlocking
section never properly terminates. Any ideas?
fun main() = runBlocking {
val lazyDeferredInt: Deferred<Int> = async(start = CoroutineStart.LAZY) {
5
}
}
main()
println("##### [scratch] done")
that print statement never executes 😢
fun main() = runBlocking {
val lazyDeferredInt: Deferred<Int> = async(start = CoroutineStart.LAZY) {
5
}
lazyDeferredInt.await()
}
main()
println("##### [scratch] done")
now I see "##### [scratch] done"
printed
* Not a contribution *phldavies
11/14/2022, 4:13 PMLAZY
you’re explicitly telling it to not start until required. As such, unless explicitly started or awaited it will not run. The outer runBlocking
scope will only complete once all child coroutines have completed, which is why you’re not seeing the last println (it’s still waiting for the unstarted async call to complete)James Eschner
11/14/2022, 4:14 PMphldavies
11/14/2022, 4:20 PM.cancel()
the deferred if you want to avoid it running in some circumstancesphldavies
11/14/2022, 4:24 PM.isActive
will return false if the deferred is either non-started or has finished (or cancelled) - either way, cancelling it in that state should be safeJames Eschner
11/14/2022, 4:26 PMfun main() = runBlocking {
// expensive operations that don't necessarily need to run
val a: Deferred<T> = async(start = CoroutineStart.LAZY) { ... }
val b: Deferred<T> = async(start = CoroutineStart.LAZY) { ... }
val c: Deferred<T> = async(start = CoroutineStart.LAZY) { ... }
if (<some condition>) {
a.await()
b.await()
c.await()
// run some logic
}
if (<some other condition) {
a.await()
// run some other logic
}
a.cancel()
b.cancel()
c.cancel()
}
But perhaps there is a better way to design this
** Not a contributionphldavies
11/14/2022, 4:54 PM.start
at the beginning of each block so that they’re executed concurrently. Possibly using a helper such as fun startAll(varargs jobs: Job) = jobs.forEach(Job::start)
.
You can also use a helper async
wrapper such as
val deferreds = mutableListOf<Deferred<*>>()
fun <T> lazyAsync(block: suspend CoroutineScope.() -> T)
= async(start = CoroutineStart.LAZY, block = block).also(deferreds::add)
val a = lazyAsync { ... }
val b = lazyAsync { ... }
val c = lazyAsync { ... }
if (<some condition>) {
startAll(a, b, c)
// logic using a.await() etc where value needed
}
// etc
deferreds.forEach(Job::cancel)
gildor
11/15/2022, 2:48 AMa, b, c
to own function and a
to one more function, so it would be easy to read and it would run in paralelgildor
11/15/2022, 2:49 AMd
and get hanging code because of thisgildor
11/15/2022, 2:53 AMfun main() = runBlocking {
if (< some condition >) {
doABC()
// run some logic
}
if (< some other condition >) {
doA()
// run some other logic
}
}
suspend fun doABC() = coroutineScope {
// Run all operations in paralel
listOf(
async { doA() },
async { doB() },
async { doC() }
).awaitAll()
}
suspend fun doA() {}
suspend fun doB() {}
suspend fun doC() {}
gildor
11/15/2022, 2:58 AMfun main() = runBlocking {
val aDeferred = async { doA() }
if ( < some condition >) {
doABC(aDeferred)
// run some logic
}
if ( < some other condition) {
aDeferred.await()
// run some other logic
}
}
suspend fun doABC(aDeferred: Deferred<Foo>) = coroutineScope {
listOf(
aDeferred,
async { doB() },
async { doB() }
).awaitAll()
}
suspend fun doA() {}
suspend fun doB() {}
suspend fun doC() {}
gildor
11/15/2022, 3:00 AM