# coroutines

Travis Griggs

02/22/2024, 7:15 PM
I've got some suspend functions that do background IO. In some cases, I just need to fork them off to run in the background, and when that's the case, I've just been using:
Copy code
CoroutineScope(<http://Dispatchers.IO|Dispatchers.IO>).launch { runTheSuspendFunction() }
But I was reading the documentation and saw this line in there:
Manual implementation of this interface is not recommended, implementation by delegation should be preferred instead.
Which leads me to ask... am I doing something I ought not? Is there a more preferred way to do this?


02/22/2024, 7:23 PM
yes. This breaks structured concurrency. If the thing which is launching this task gets cancelled then you have no way to automatically cancel
. Rather than pulling a coroutine scope out of thin air like you’re doing, you should:
Copy code
class SomeThing {
  val scope = CoroutineScope(...)
  fun runFunctionAsync() {
    scope.launch(<http://Dispatchers.IO|Dispatchers.IO>) { runTheSuspendFunction() }

  fun close() = scope.cancel()
🙌 1
In general a coroutine scope should always be tied to some lifecycle. That could the the lifetime of a stack frame, the lifetime of an object which offers resource cleanup (
), or the lifetime of platform thing like a ViewModel or a compose effect.