https://kotlinlang.org logo
#coroutines
Title
# coroutines
d

dave08

10/31/2018, 1:38 PM
Then
Copy code
var currWork: Job = null
launch { if (cancelCurrWork) currWork?.cancel() }
currWork = doWork()
?
d

Dominaezzz

10/31/2018, 1:41 PM
That looks racy.
So you want to call
doWork
and cancel it immediately?
d

dave08

10/31/2018, 1:43 PM
I have a singleton running in the Application scope of an Android app running
doWork()
... I need to cancel the doWork when I receive an Intent from a BroadcastReceiver
d

Dominaezzz

10/31/2018, 1:44 PM
Oh, then yes, use launch and get the reference to the Job.
d

dave08

10/31/2018, 1:45 PM
But here, I don't really need to
launch
the
doWork
because it's running a list of these synchonously... the only reason I'm `launch`ing is to get the Job to be able to cancel it... is there a better way to do this?
d

Dominaezzz

10/31/2018, 1:49 PM
There's no way to (gracefully) cancel it without a reference to the Job.
👍🏼 1
j

Jonathan

10/31/2018, 2:18 PM
Copy code
suspend fun main() {
	coroutineScope {
		val job = launch { ... }
		
		
		job.cancel() // <-- this cancel only the child, not the parent scope
	}
}
d

dave08

10/31/2018, 2:24 PM
Right, but I need that job reference outside the
coroutineScope { }
, so that I can stop that function's execution from another function in the class.
Copy code
class WorkDoer(supervisorScope: CoroutineScope): CoroutineScope by supervisorScope {
      var currJob: Job? = null
      var currJobId: Int = 0
      suspend fun doWork(id: Int) {
            currJobId = id
            currJob = launchInScope { .... }
     }
      fun cancelWork(id: Int) = if (currJobId == id) currJob?.cancel()
}
This is closer to my use case.
I guess this case is racy though, since
currJob
might be a different one by the time cancel is requested on the previous one... I'm thinking of maybe using a Mutex..? 🤔
d

Daniel Tam

10/31/2018, 3:12 PM
Copy code
val job = Job()
coroutineScope {
  launch(job) {...}
}
d

dave08

10/31/2018, 3:15 PM
What is there to gain with that @Daniel Tam? Isn't it the same as
val job = launchInScope { }
? Each piece of work needs its own Job, so that a specific piece of work with an
id
can be cancelled...
d

Daniel Tam

10/31/2018, 3:17 PM
I've probably misunderstood the problem then
d

dave08

10/31/2018, 3:18 PM
WorkDoer
that I posted above is very similar to my use case, thanks anyways 🙂!
d

Daniel Tam

10/31/2018, 3:21 PM
so you want to always cancel the most recent job?
or do you only want to cancel a job of a certain id, and if it's a previous id then we do nothing
d

dave08

10/31/2018, 3:22 PM
I need to cancel a job only if it has that id, since it could have finished and gone to the next one by the time I'm trying to cancel it...
d

Daniel Tam

10/31/2018, 3:25 PM
is the id necessary? Can you just provide a reference to the job?
d

dave08

10/31/2018, 3:26 PM
Yes it is, that's what I send in the Android Intent...
j

Jonathan

10/31/2018, 3:26 PM
I need that job reference outside the
coroutineScope { }
But
coroutineScope {}
suspend until the job completes....
d

dave08

10/31/2018, 3:27 PM
Right, but this is running in an Android IntentService, and the cancellation needs to be sent from a Notification through a BroadcastReceiver... which means two different threads.
2 Views