Kotlinx.coroutines: Support runBlocking with arbitrary context

Created on 29 Jan 2018  ·  5Comments  ·  Source: Kotlin/kotlinx.coroutines

The current behavior of runBlocking with a specified context is somewhat low-level and hardly used in practice. In particular, unless the dispatcher that is passed to runBlocking implements EventLoop (usually - not), then runBlocking creates its own private event loop and uses it as dispatcher, while ignoring the dispatcher that was passed to it in the context.

This proposal is to change this behavior so that runBlocking(UI) { ... } would result in blocking the current thread and running the code in the context of UI dispatcher, consistently with how other coroutine builders (launch, async, etc) operate. It looks that this is going to be less-surprising behavior.

enhancement

Most helpful comment

Let me clarify the consistency here. For all other coroutine builders like launch, using them with a context:

launch(ctx) { ... }

is equivalent to using them without context, but relying on withContext to change it:

launch { withContext(ctx) { ... } }

This change essentially brings the same behavior to runBlocking function.

All 5 comments

IMHO, runBlocking(UI) { ... } is confusing because it can be unclear if UI context or calling thread will be blocked (and even more confusing with the current behavior).
I think the runBlocking method that takes a CoroutineContext parameter should be deprecated in favor of another one named like runBlockingInContext used the same way.

That way:

runBlocking {
    ... // Code is run on the caller thread
}

The code above obviously blocks the caller thread until the coroutine inside the block reaches the last line.

runBlockingInContext(UI) {
   ... // Code is run in the UI coroutine context
}

The code above blocks the calling thread but runs the suspend lambda in the UI coroutine context.

The runBlockingInContext method could under the hood just use runBlocking (no parameter) and withContext (using the passed coroutine context).

runBlocking + withContext = runBlockingWithContext

However I personally prefer the original proposal.

I think runBlocking + optional context is better, I don't see why we should add one more function, Kotlin default arguments allow to avoid additional method without any drawbacks

Let me clarify the consistency here. For all other coroutine builders like launch, using them with a context:

launch(ctx) { ... }

is equivalent to using them without context, but relying on withContext to change it:

launch { withContext(ctx) { ... } }

This change essentially brings the same behavior to runBlocking function.

IMHO, runBlocking(UI) { ... } is confusing because it can be unclear if UI context or calling thread will be blocked

Doesn't passing it a specific context describe the expected behavior? I thought the idea was that it would block the UI context unless a suspend occurs within the provided block? At least that's what I get out of the name runBlocking..

It does seem weird that this essentially is a discussion to create a new method that exposes the same parameters as what already exists on runBlocking. 🤷‍♂️

👍 for making runBlocking consistent with the other builders.

Was this page helpful?
0 / 5 - 0 ratings