I need to launch some code frequently in a single non-UI thread. I am trying to use actors to achieve it:
class SomeClass {
@OptIn(ObsoleteCoroutinesApi::class)
private fun CoroutineScope.myActor() = actor<MyMessage> {
for (message in channel) {
delay(5000)
Log.d("SomeClass", "Message ${Thread.currentThread().name}")
}
}
private var channel: SendChannel<MyMessage>? = null
private val scope = CoroutineScope(Dispatchers.Default)
fun send() {
scope.launch {
if (channel == null) {
channel = myActor()
}
channel?.send(IncCounter)
}
}
sealed class MyMessage
}
And then calling it:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState)
val c = SomeClass()
c.send()
c.send()
c.send()
c.send()
}
Output:
Message DefaultDispatcher-worker-8
Message DefaultDispatcher-worker-2
Message DefaultDispatcher-worker-8
Message DefaultDispatcher-worker-2
So, as I see it creates more than one thread. How to implement frequently messaging handling in a single thread?
CodePudding user response:
Try to use limitedParallelism(1)
function on CoroutineDispatcher
:
private val scope = CoroutineScope(Dispatchers.Default.limitedParallelism(1))
OR
private fun CoroutineScope.myActor() = actor<MyMessage>(context = Dispatchers.Default.limitedParallelism(1)) { ... }