title: NetworkOnMainThreadException while launching coroutines via `Dispatchers.IO`
body: <p>I'm attempting to make a basic network call using the View/ViewModel/UseCase/Repository pattern. The main async call is performed via Coroutines, which are both launched using <code>Dispatchers.IO</code>.</p>
  
  <p>To start, here is the relevant code:</p>
  
  <p><strong>ViewModel:</strong></p>
  
  <pre><code>class ContactHistoryViewModel @Inject constructor(private val useCase: GetContactHistory) : BaseViewModel() {
      // ...
      fun getContactHistory(userId: Long, contactId: Long) {
          useCase(GetContactHistory.Params(userId, contactId)) { it.either(::onFailure, ::onSuccess) }
      }
  }
  </code></pre>
  
  <p><strong>GetContactHistory UseCase:</strong></p>
  
  <pre><code>class GetContactHistory @Inject constructor(private val repository: ContactRepository) : UseCase&lt;ContactHistory, GetContactHistory.Params&gt;() {
  
      override suspend fun run(params: Params) = repository.getContactHistory(params.userId, params.contactId)
      data class Params(val userId: Long, val contactId: Long)
  }
  </code></pre>
  
  <p><strong>Base UseCase class used above:</strong></p>
  
  <pre><code>abstract class UseCase&lt;out Type, in Params&gt; where Type : Any {
  
      abstract suspend fun run(params: Params): Either&lt;Failure, Type&gt;
  
      operator fun invoke(params: Params, onResult: (Either&lt;Failure, Type&gt;) -&gt; Unit = {}) {
          val job = GlobalScope.async(Dispatchers.IO) { run(params) }
          GlobalScope.launch(Dispatchers.IO) { onResult(job.await()) }
      }
  }
  </code></pre>
  
  <p><strong>Finally, the Repository:</strong></p>
  
  <pre><code>class ContactDataRepository(...) : SyncableDataRepository&lt;ContactDetailDomainModel&gt;(cloudStore.get(), localStore),
          ContactRepository {
  
      override fun getContactHistory(userId: Long, contactId: Long): Either&lt;Failure, ContactHistory&gt; {
          return request(cloudStore.get().getContactHistory(userId, contactId), {it}, ContactHistory(null, null))
      }
  
      /**
       * Executes the request.
       * @param call the API call to execute.
       * @param transform a function to transform the response.
       * @param default the value returned by default.
       */
      private fun &lt;T, R&gt; request(call: Call&lt;T&gt;, transform: (T) -&gt; R, default: T): Either&lt;Failure, R&gt; {
          return try {
              val response = call.execute()
              when (response.isSuccessful) {
                  true -&gt; Either.Right(transform((response.body() ?: default)))
                  false -&gt; Either.Left(Failure.GenericFailure())
              }
          } catch (exception: Throwable) {
              Either.Left(Failure.GenericFailure())
          }
      }
  }
  </code></pre>
  
  <p><strong>Summary:</strong>
  Placing a debug breakpoint in that <code>catch{}</code> block in the repository (seen directly above) shows that a <code>android.os.NetworkOnMainThreadException</code> is being thrown. This is strange, given that both coroutines are launched with a context of <code>Dispatchers.IO</code>, not <code>Dispatchers.Main</code> (Android's main UI thread).</p>
  
  <p><strong>Question:</strong>
  Why is the aforementioned exception being thrown, and how can this code be corrected?</p>