benny.huo
04/21/2019, 1:55 AMjoin
on an exceptionally completed job. After days digging, I figure out that if the join
call falls into the fast-path or successfully suspending, a CancellationException will be thrown in this case, but if the join
call falls into the joinSuspend
path but not successfully suspending, no CancellationException will happen. I just wonder that is it a bug to get inconsistent result from join
with the same code?
I have created a gist here https://gist.github.com/enbandari/0321cffa792e0f98d90e0e77682aeaed to make it more clear.Thomas
04/21/2019, 4:55 PMAllan Wang
04/22/2019, 6:13 AMrunBlocking
safe for production if we have helper suspended functions, and are using an interface where it’s okay to block the thread?
For instance, I’m building a notification widget, which requires updates to be done in onDataSetChanged
, before the provider will apply the dataThomas
04/22/2019, 7:21 PMval channel = ConflatedBroadcastChannel(Unit)
channel.asFlow().produceIn(GlobalScope).poll()!!
If I understand correctly this shouldn’t be happening because the channel has a default Unit
value. The following code, however, does not crash:
val channel = ConflatedBroadcastChannel(Unit)
channel.openSubscription().poll()!!
I don’t get why this works but the first example doesn’t. Could someone please explain this behaviour?sdeleuze
04/23/2019, 6:58 AMFlow
to a non-suspending function that returns Flow
. Is this the correct way to do that?
suspend fun suspendingFlow(): Flow<String> { ... }
fun nonSuspendingFlow() = flow {
suspendingFlow().collect {
emit(it)
}
}
addamsson
04/23/2019, 6:59 AMTest
service to fail even if the Job
fails because each Job
is independent, I just want the error handling.
class Test : CoroutineScope {
override val coroutineContext = Dispatchers.Default + SupervisorJob()
fun doSomething(): Job {
val handler = CoroutineExceptionHandler { _, exception ->
// log error
}
return launch(handler) {
// do things
}
}
}
ribesg
04/23/2019, 8:59 AMsuspend fun <T> withMinimumDuration(duration: Long, block: suspend CoroutineScope.() -> T) =
coroutineScope {
val delay = async { delay(duration) }
val task = async { block() }
delay.join()
task.await()
}
Jakub Aniola
04/23/2019, 10:36 AMkawmra
04/24/2019, 7:02 AMResult<T>
.
I have the code like following:
launch {
runCatching { doSomething() }
.onSuccess {
doSuccessProcess(it)
}
.onFailure {
doFailureProcess()
}
}
I wanna handle errors if doSomething()
fails.
But this code catches CancellationException
as well when launch
was canceled.
Are there any problems? Can I just ignore the CancellationException
?jw
04/24/2019, 1:11 PMjust(1, 2, 3)
-> flowOf(1, 2, 3)
error(Exception())
-> flow { throw Exception() }
addamsson
04/25/2019, 12:51 PMCoroutineScope
, but in the Fan-in examples it uses suspending functions. Is there a practical difference between these two approaches? ---->
@JvmStatic
fun main(args: Array<String>) = runBlocking {
val channel = Channel<String>()
launch { sendString(channel, "foo", 200L) }
launch { sendString(channel, "BAR!", 500L) }
repeat(6) {
// receive first six
println(channel.receive())
}
coroutineContext.cancelChildren() // cancel all children to let main finish
}
suspend fun sendString(channel: SendChannel<String>, s: String, time: Long) {
while (true) {
delay(time)
channel.send(s)
}
}
versus
@JvmStatic
fun main(args: Array<String>) = runBlocking {
val channel = Channel<String>()
sendString(channel, "foo", 200L)
sendString(channel, "BAR!", 500L)
repeat(6) {
// receive first six
println(channel.receive())
}
coroutineContext.cancelChildren() // cancel all children to let main finish
}
fun CoroutineScope.sendString(channel: SendChannel<String>, s: String, time: Long) = launch {
while (true) {
delay(time)
channel.send(s)
}
}
Both are doing the same if I understand the concepts correctly and also produce the same output. When should I use which?Zach Klippenstein (he/him) [MOD]
04/25/2019, 5:29 PMproduce
builder doesn’t take a CoroutineStart
parameter? (cc @elizarov)marcoferrer
04/25/2019, 6:27 PMmarcoferrer
04/25/2019, 6:28 PMspierce7
04/25/2019, 7:38 PMtasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile) {
kotlinOptions.freeCompilerArgs += ["-Xuse-experimental=kotlinx.coroutines.ExperimentalCoroutinesApi"]
}
streetsofboston
04/25/2019, 8:53 PMval xHandler = CoroutineExceptionHandler { c, e ->
println("Handled Crash in coroutine $c")
e.printStackTrace(System.out)
}
fun launch_handleExceptionInCoroutineExceptionHandler(): Unit = runBlocking(xHandler) {
launch(<http://Dispatchers.IO|Dispatchers.IO> + xHandler) {
delay(1000)
throw Exception("Some Exception 1")
}
delay(2000)
}
fun main() {
Thread.setDefaultUncaughtExceptionHandler { t, e ->
println("App Crash in thread $t")
e.printStackTrace(System.out)
}
launch_handleExceptionInCoroutineExceptionHandler()
}
The xHandler
is never called.
The output is produced by the default-uncaught-exception-handler instead.
I expected the xHandler
to be called.
If I provide another scope to the launch
, eg GlobalScope.launch { ... }
it works as expected and the xHandler
is called.
Why is the xHandler
not called when using the `runBlocking`’s scope?
(just to be sure, I provided the xHandler
in 2 places, when calling runBlocking
and when calling `launch`…)simon.vergauwen
04/26/2019, 7:52 AMjava.util.concurrent.ThreadPoolExecutor
with a keepAlive of 0, will it respect that keepAlive
as a CoroutineContext
?Vsevolod Tolstopyatov [JB]
04/26/2019, 8:44 AMkotlinx.coroutines
1.2.1 is here!
Changelog:
• Infrastructure for testing coroutine-specific code in kotlinx-coroutines-test
(read more here https://github.com/Kotlin/kotlinx.coroutines/tree/master/kotlinx-coroutines-test#runblockingtest). Thanks Sean McQuillan for the contribution!
• Job.asCompletableFuture
extension in jdk8 module
• New operators in `Flow`: switchMap
, debounce
, sample
• Various fixes and improvements, full changelog: https://github.com/Kotlin/kotlinx.coroutines/releases/tag/1.2.1altavir
04/26/2019, 10:50 AMn
subsequent elements and join them into one).altavir
04/26/2019, 11:25 AMFlow
map operation parallelizable?altavir
04/26/2019, 2:59 PMflowOn
. I am not sure I've done context switching correctly. And I can't use internal functions like getCancellationException
for proper exception propagation. I will open a ticket for this.Andrew Gazelka
04/26/2019, 10:44 PMResource
is
suspend fun take(priority: Int = 0, immediate: Boolean = false)
where a task with a lower priority will be scheduled first and higher later. The immediate
argument will determine whether the currently executing process should be interrupted if take(...)
has a lower priority than the currently executing task. A resource is given back with Resource#giveBack()
.
Any recommendations on how I could do this idiomatically?Lulu
04/27/2019, 12:43 AMefemoney
04/27/2019, 11:11 AMThread.UncaughtExceptionHandler
with `CoroutineExceptionHandler`s that is a globally handled exception handler?ansman
04/27/2019, 3:12 PMsuspendCancellableCoroutine
? I need to work around a memory leak and I was planning on doing that by keeping a weak ref to the continuationaltavir
04/28/2019, 6:47 AMval deferred = coroutineScope {
async(start = CoroutineStart.LAZY) { println("async") }
}
deferred.await()
causes a infinite block. I understand that it is caused by interference of lazy deferred with structured concurrency, but it significantly reduces application for lazy deferred. Is it intended to be this way?littlelightcz
04/28/2019, 8:58 AMrunBlocking(<http://Dispatchers.IO|Dispatchers.IO>) {
val myList = mutableListOf(1).asObservable()
launch {
myList.asFlow().collect { println("A $it") }
}
delay(1000)
myList += 2
launch {
myList.asFlow().collect { println("B $it") }
}
delay(1000)
}
Which produces:
A 1
B 1
B 2
Is there some sort of non-terminal collect
yet that would listen for further changes, so that I would see A 2
in the output when myList
gets updated?halim
04/28/2019, 9:19 AMi am confuse with this syntax
fun task(bloc: suspend () -> Unit) { .... }
what does mean call suspend function inside regular function ?Paul Woitaschek
04/29/2019, 3:17 PMstartActivityForResult
and it suspends until onActivityResult
is called.
Is using a Channel the right way to do that?
kotlin
class MyActivty : Activity(){
private val channel = Channel<Uri>()
override fun onActivityResult(data: Intent){
val uri = data.data
channel.offer(uri)
}
suspend fun soSthWithStartActivtyForResult() : Uri {
startActivityForResult(intent, 42)
return channel.receive()
}
}
streetsofboston
04/29/2019, 4:05 PMval xHandlerParent = CoroutineExceptionHandler { c, e ->
println("Parent Handled Crash")
}
val xHandlerLeaf = CoroutineExceptionHandler { c, e ->
println("Leaf Handled Crash")
}
fun main() {
CoroutineScope(xHandlerParent).launch(xHandlerLeaf) {
delay(1000)
throw Exception("Some Exception 1")
}
Thread.sleep(2000)
}
prints out Leaf Handled Crash
.
However, I expected the output to be Parent Handled Crash
, because an exception bubbles up to the top-most parent and CoroutineExceptionHandler
of that top-most parent should be used.
If I replace CoroutineScope(xHandlerParent). ...
with runBlocking { ... }
, the xHandlerLeaf
is not used, as I expected, because the top-most parent is used and that is a scoped-parent that just throws the exception up the call-stack.
I’m not sure if this is a bug or if I don’t understand how exceptions are handled 🙂streetsofboston
04/29/2019, 4:05 PMval xHandlerParent = CoroutineExceptionHandler { c, e ->
println("Parent Handled Crash")
}
val xHandlerLeaf = CoroutineExceptionHandler { c, e ->
println("Leaf Handled Crash")
}
fun main() {
CoroutineScope(xHandlerParent).launch(xHandlerLeaf) {
delay(1000)
throw Exception("Some Exception 1")
}
Thread.sleep(2000)
}
prints out Leaf Handled Crash
.
However, I expected the output to be Parent Handled Crash
, because an exception bubbles up to the top-most parent and CoroutineExceptionHandler
of that top-most parent should be used.
If I replace CoroutineScope(xHandlerParent). ...
with runBlocking { ... }
, the xHandlerLeaf
is not used, as I expected, because the top-most parent is used and that is a scoped-parent that just throws the exception up the call-stack.
I’m not sure if this is a bug or if I don’t understand how exceptions are handled 🙂yousefa2
04/29/2019, 4:07 PMxHandlerLeaf
handles the exception which stops it from propagating to it's parent. That's why you don't get it in the parent.streetsofboston
04/29/2019, 4:08 PMfun main() {
runBlocking{
launch(xHandlerLeaf) {
delay(1000)
throw Exception("Some Exception 1")
}
}
Thread.sleep(2000)
}
the xHandlerLeaf
is not used.CoroutineExceptionHandler
of that parent is used.xHandlerParent
does handle the exception, as I expect:
fun main() {
CoroutineScope(Dispatchers.Default).launch(xHandlerParent) {
launch(xHandlerLeaf) {
delay(1000)
throw Exception("Some Exception 1")
}
}
Thread.sleep(2000)
}
Martín Ickowicz
04/29/2019, 7:25 PMCoroutineExceptionHandler
consumes the exception and does not propagates it
in your last example you are throwing a new exception, which is caught by the parent scopestreetsofboston
04/29/2019, 7:32 PMMartín Ickowicz
04/29/2019, 7:37 PM