title: SQLite transactions freeze on Dispatchers.Main but work on Dispatchers.Default and Dispatchers.IO
body: <p>I am working on a project on which I unfortunately cannot use ROOM to access the database because it depends heavily on cursors which read databases created as a result of api calls</p>
  
  <p>So to make this work I am using a normal <code>SQLiteOpenHelper</code> to get a <code>readableDatabase</code> and perform the queries using something like </p>
  
  <pre><code>withContext(Dispatchers.IO) { db.execSQL(.....) }
  </code></pre>
  
  <p>I faced a problem with transactions which created deadlocks, for example this would cause problems</p>
  
  <pre><code>suspend fun readDataFromServer() {
      withContext(dispatchers.IO) { db.beginTransaction() } 
      val inputStream = withContext(dispatchers.IO) { client.getDataStream() }
  
      while(true) {
         withContext(dispatchers.IO) { //code here that reads from the input stream until it finds a separator 
         }
         withContext(dispatchers.Default) { 
             //code that does some calculations that may take anywhere from 500 to 1500 ms
         }
  
         withContext(dispatchers.IO) { 
             //code that saves the data in the appropriate form in my db
         }
  
      }
      withContext(dispatchers.IO) { 
           db.setTransactionSuccessful() 
           db.endTransaction()
      }
  
  }        
  </code></pre>
  
  <p>(note that the above is some off the top of my head dummy code, I don't have access to my project atm)</p>
  
  <p>I researched it and it seems that the problem was that the transaction has to start and finish at the same thread, so when I used withContext to change the dispatchers (even if that was the same dispatcher) it would cause a deadlock</p>
  
  <p>In the end I solved my problem by wrapping the whole function in one withContext but I noticed something curious</p>
  
  <p>normally the function would start from something like:</p>
  
  <pre><code>launch(Dispatchers.Main) {
      readDataFromServer()
  }
  </code></pre>
  
  <p>and that would cause a freeze, but when I tried launching it from other dispatchers it would work, so</p>
  
  <pre><code>launch(Dispatchers.Default) {
      readDataFromServer()
  }
  </code></pre>
  
  <p>and</p>
  
  <pre><code>launch(Dispatchers.IO) {
      readDataFromServer()
  }
  </code></pre>
  
  <p>both seem to work</p>
  
  <p>I was wondering why that is , and if this may be a fluke because in essence I don't use more than one thread for my operations</p>
  
  <p>is wrapping it in the same withContext the correct answer ? or could is using the launch(Dispatchers.Default) correct too?</p>
  
  <p>I am asking because between reading from the server and writing to the database I do some quite intensive work , and it seems incorrect that I have to do that work in the IO dispatcher instead of the Default one</p>