Skip to content

Error invoking produce inside a suspending method #645

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
fabioCollini opened this issue Oct 2, 2018 · 2 comments
Closed

Error invoking produce inside a suspending method #645

fabioCollini opened this issue Oct 2, 2018 · 2 comments

Comments

@fabioCollini
Copy link

I am trying to use the channels and I am getting some strange behaviour. Everything works defining methods as CoroutineScope extension methods but there is a deadlock defining the same method as suspend and invoking coroutineScope at the beginning. In the channels guide all the methods are defined as CoroutineScope extension methods but it would be useful to define them as suspending. Here there is a test to reproduce it, testNormal and testExtension work correctly but testScope never finish:

class ExampleUnitTest {
    @Test
    fun testNormal() {
        runBlocking {
            launch(Dispatchers.IO) {
                val channel = produce {
                    send(1)
                    send(2)
                    send(3)
                }

                channel.consumeEach {
                    println(it)
                }
            }
        }
    }

    @Test
    fun testExtension() {
        runBlocking {
            launch(Dispatchers.IO) {
                val channel = produceExtension()

                channel.consumeEach {
                    println(it)
                }
            }
        }
    }

    @Test
    fun testScope() {
        runBlocking {
            launch(Dispatchers.IO) {
                val channel = produceCoroutineScope()

                channel.consumeEach {
                    println(it)
                }
            }
        }
    }

    private suspend fun produceCoroutineScope(): ReceiveChannel<Int> = coroutineScope {
        produce {
            send(1)
            send(2)
            send(3)
        }
    }

    private fun CoroutineScope.produceExtension(): ReceiveChannel<Int> = produce {
        send(1)
        send(2)
        send(3)
    }
}

I have just tryed to update to version 0.30.0-eap13, the problem remains using it.

@fvasco
Copy link
Contributor

fvasco commented Oct 2, 2018

Hi @fabioCollini
in your testScope the produce factory have to complete before coroutineScope exits, so produceCoroutineScope cannot terminate.

You can use a different scope, like GlobalScope, or a channel capacity greater or equal to three (or CONFLATED, UNLIMITED).

I got a similar issue using the code GlobaScope.async { actor { ... channel.receive() ... } }, using this code there is no way to get the actor asynchronously, I have to use a GlobalScope explicitly (and this is the goal of CoroutineScope).

@elizarov
Copy link
Contributor

@fvasco Thanks for the answer. I'm closing this one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants