So this compiles but doesnt work as I expected at ...
# announcements
e
So this compiles but doesnt work as I expected at all, why?
s
Not sure what you expected, but to me it looks like your code would never get past the
SENDING 2
print-out. The
channel
is a rendez-vous channel and the first call to
channel.send(...)
will suspend forever, since there is no active listener/consumer. There is no active listener/consumer because the first
runBlocking
never returns and the second
runBlocking
is never called.
e
I thought new
newSingleThreadContext
would create a new ~thread for each coroutine so it wouldnt get blocked at
Sending 2
s
You use`runBlocking`. This means that this will block until the code in its provided block/lambda has finished. It will never finish. This means the second
runBlocking
is never called and no listener will listen.
e
Yeah but what does
newSingleThreadContext
do then?
s
That will make the code inside the runBlocking run in that thread. Still, it (runBlocking) waits for that piece of code in the lambda to end, regardless on which thread that code is running.
You'd want to use
launch
instead, not runBlocking:
val scope = CoroutineScope(newSingleThreadContext();  .... scope.launch { .... } .... scope.launch { ... }
e
If its seperate thread it wouldnt block tho, if it isnt a new thread why its called
newSingleThread..
This runs fine
Copy code
Executors.newSingleThreadExecutor().execute {
        runBlocking {
            println("Listening")
            for (i in channel) {
                println("${Thread.currentThread()} RECEIVED $i")
            }
        }
    }
I expected same from
newSingleThread..
too
s
The function
runBlocking
blocks until its lambda has finished. Look at the documentation of this function. It doesn't matter on which thread that code in the lambda is running
e
So it blocks the whole application? Not just the thread it runs on
s
The function
runBlocking
blocks the thread on which the runBlocking is called.
Your second example will fail/hang as well if you put both
runBlocking
calls inside the
.execute { ...  }
block
e
ahh ok, the parameter
newSingleThread..
doesnt change the thread so it blocks now I get it thx
s
Exactly. It tells the
runBlocking
on which thread to run its code-block/lambda. The runBlocking itself does not change on which thread the following code is executed.
e
yep thx again
My real problem is trying to consume
ReceiveChannel<T>
from a regular func. Couldnt find the right construct. Create thread pool and go for runBlocking? Or is there anything better?
s
You can't consume a channel on a regular function. You'd need a suspend function / coroutine. You can produce values onto a channel, though, by calling
offer
instead of
send
.
You'd hardly use runBlocking, unless you need to bridge from a suspending world (eg a library that exposes suspend funs, channels, flows) to a non-suspending/regular world (eg plain Java)
Use
scope.launch { ... your coroutine code here ... }
to build a coroutine and consume your channel from within those coroutines
e
Thats what Im kind of trying to do actually, offering non-suspending API to java world. Taking a callback function as parameter and consuming every elem of
ReceiveChannel<T>
with that function.
As I understand
CoroutineScope(<http://Dispatchers.IO|Dispatchers.IO>).launch{}
(channel will offer its values from network thats why I went with IO) seems approp. for my use case, thx for the help