Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Realm access from incorrect thread while using realm with coroutines

I'm trying to use realm with kotlin coroutines and make queries inside a new thread using withContext()

What I observe is that threads are switching in the loop making realm throws this exception: Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created.

withContext(Dispatchers.IO) {
            val realm = Realm.getDefaultInstance()
            val images = mutableListOf<String>("id1", "id2", ...)
            for (imageId in images) {
                 println("THREAD : ${Thread.currentThread().name}")
                 val image = realm.where<Image>().equalTo("imageId", imageId).findFirst()
                 delay(1000) // Can lead to an actual switching to another thread
            }
            realm.close()
}

As the dispatchers.IO documentation mention here: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/-i-o.html

"This dispatcher shares threads with a [Default][Dispatchers.Default] dispatcher, so using * withContext(Dispatchers.IO) { ... } does not lead to an actual switching to another thread; * typically execution continues in the same thread."

I don't understand why thread are switching in the loop. How to manage realm instance with coroutine properly ?

like image 545
CuirMoustachu Avatar asked Dec 28 '18 15:12

CuirMoustachu


2 Answers

You can run Realm in another new single thread in a Coroutine. For example

val dispatcher =  Executors.newSingleThreadExecutor().asCoroutineDispatcher()
jobs.launch(dispatcher) {
  // create new Realm instance
}
like image 88
chriskrueger Avatar answered Nov 17 '22 09:11

chriskrueger


Every time a coroutine is suspended, at the time it's resuming the dispatcher will find a thread for it to run on. It's quite likely that it will be a different thread than the one it ran on previously.

like image 6
Marko Topolnik Avatar answered Nov 17 '22 10:11

Marko Topolnik