If I have this: ```runBlocking { SMR() println...
# coroutines
e
If I have this:
Copy code
runBlocking {
  SMR()
  println("test")
}
it hangs when SMR is like:
Copy code
suspend fun SMR() = withContext(dispatcher) {
  launch { ... }
}
But not if it's like:
Copy code
suspend fun CoroutineScope.SMR() {
  launch { ... }
}
From the look of things withContext should just grab the old context, merge with new context and dispatch if the dispatcher changed.
b
Is
dispatcher
here a single-threaded dispatcher? Is it the same dispatcher/thread where runBlocking was called?
e.g. Dispatchers.Main
t
This is expected behavior due to structured concurrency. The first example of withContext, the inner
this
is a new child coroutine scoped to the parent caller. The inner coroutine will not complete and return until all of its children are completed. Essentially if you stop the work inside of launch after some time, it will function closer to your expectation. In the second example no new coroutineScope is created, thus the launch is bound to the caller's coroutine scope
e
@Trevor Stone what would the correct way to go about this be?
t
What are you trying to do?
j
@Exerosis
withContext
is not only switching the context here, it also creates a nested scope (like
coroutineScope { ... }
) and waits for all children to finish. If you just want to launch with added context, just pass the extra context directly to launch:
Copy code
fun CoroutineScope.SMR() {
  launch(dispatcher) { ... }
}
Also, avoid making a
suspend
function with
CoroutineScope
receiver. It's confusing because
suspend
functions are usually expected to finish their work before returning, while
CoroutineScope
extensions are expected to return almost immediately and launch child coroutines
e
@Joffrey Ah I see, I feel like I keep making this same mistake. I don't really understand the advantages of it working in this way. However I think in my case I want a CoroutineScope extension and you are right I don't need to mark it as suspend.