tomas-mrkvička
02/04/2022, 8:46 PMrunBlocking
. The documentation says that it should be used in main
, tests and libraries to bridge two worlds. I found zero information about structured concurrency within plain command line applications. Lets say I have a tool which migrates data from one source to another and I would like to use concurrent executions for some parts of the whole migration process. Now, should I define runBlocking
somewhere "in the middle", or how to use coroutines in the world where no life cycle managers exists?
ThanksNick Allen
02/04/2022, 9:01 PMrunBlocking
is your lifecycle. It gives you a CoroutineScope
as the lambda receiver to represent the lifetime of the runBlocking
call. runBlocking
won't return until all coroutines launched with that CoroutineScope
have finished.
For example, if you were to just call GlobalScope.launch
then main could return and end the process before the coroutine had finished.Joffrey
02/04/2022, 9:01 PMrunBlocking
"somewhere in the middle"Nick Allen
02/04/2022, 9:04 PMrunBlocking
, just avoid calling it from within a coroutine. If runBlocking
depends on code waiting to run on threads blocked by runBlocking
you get a deadlock.tomas-mrkvička
02/04/2022, 9:10 PMJoffrey
02/04/2022, 9:17 PMrunBlocking
from coroutines/suspend functions. But otherwise if the goal is to synchronously call a suspend function from the non-suspending world, it's what runBlocking
is for. And in the context of CLI applications, this is often the case. Usually though, you can bubble up the suspend
keyword almost all the way up to the main
method (but you don't have to)Nick Allen
02/04/2022, 9:21 PMrunBlocking
anytime you want to hold up a thread until you are done with some coroutine work.
So main
is a good example. Also, synchronous callback APIs where the purpose is to allow you to do side effects, rather that to give you a result. Or if you need to implement a synchronous interface or override a synchronous method.
If your caller must be synchronous but you want to use coroutines, that's where you need to use runBlocking
.tomas-mrkvička
02/04/2022, 9:28 PMK Merle
02/05/2022, 4:58 AMrunBlocking
half way down the pipeline. It would be easy to have a long waited suspend function easily misplaced into the runBlocking
and have a unwanted delay in your code execution.
For example, at my work we use internal authentication library that uses runBlocking
to add authentication headers and it's causing every request to have a longer timeout then we want inside of the app, because runBlocking
had code inside that was blocking the thread.
So in general, I would avoid it.tomas-mrkvička
02/05/2022, 7:57 AMJoffrey
02/05/2022, 10:29 AMrunBlocking
? If the library takes a long time to compute those headers, and exposes a blocking API for it that guarantees the work is done when it returns, you'll have to wait and block the caller thread anyway. It could be using something entirely different, not even coroutines, and the result would be the same.K Merle
02/05/2022, 11:53 AMrunBlocking
, not the runBlocking
itself. It was misused.Joffrey
02/05/2022, 12:05 PMrunBlocking
inside, and calling a third-party library within runBlocking
. Is this correct? Was that third-party library exposing a blocking API?K Merle
02/05/2022, 1:16 PMlhwdev
02/06/2022, 11:51 PM<http://Dispatchers.IO|Dispatchers.IO>
and runInterruptible
.runInterruptible
helps translating cancellation calls to Thread interrupt which will work for traditional java IO.Klitos Kyriacou
02/13/2022, 6:18 PMyou can bubble up thecan you explain why you said "almost"?keyword almost all the way up to thesuspend
methodmain
Joffrey
02/14/2022, 9:14 AMmain
function itself suspend
. I was cautious because if you use some framework, maybe you don't have access to main
, or main
may just call the framework (which you don't control), which in turn calls you through interfaces or classes in a blocking way. When in this situation, your "entrypoint" because something else than main
and so you may not be able to make that one suspend
(let alone go all the way up to main
with suspend
functions) - but you can use runBlocking
there, that's what it's for