取消整个协程作用域CoroutineScope
kotlin
复制代码
Log.i("yang", "Main Start")
val mScope = CoroutineScope(Dispatchers.IO)
val mJob1 = mScope.launch {
try {
Log.i("yang", "Job1 Start")
delay(1000)
Log.i("yang", "Job1 End")
} catch (e: Exception) {
Log.i("yang", "Job1 Cancelled e = ${e.message}")
}
}
val mJob2 = mScope.launch {
try {
Log.i("yang", "Job2 Start")
delay(2000)
Log.i("yang", "Job2 End")
} catch (e: Exception) {
Log.i("yang", "Job2 Cancelled e = ${e.message}")
}
}
Log.e("yang", "Main Continue")
Thread.sleep(500)
mScope.cancel()
Log.e("yang", "Main Cancel")
Log.i("yang", "Main End")
// log
2025-01-06 17:36:52.588 1752-1752 yang com.example.myapplication I Main Start
2025-01-06 17:36:52.593 1752-1752 yang com.example.myapplication E Main Continue
2025-01-06 17:36:52.593 1752-2367 yang com.example.myapplication I Job1 Start
2025-01-06 17:36:52.594 1752-2391 yang com.example.myapplication I Job2 Start
2025-01-06 17:36:53.094 1752-1752 yang com.example.myapplication E Main Cancel
2025-01-06 17:36:53.094 1752-1752 yang com.example.myapplication I Main End
2025-01-06 17:36:53.094 1752-2367 yang com.example.myapplication I Job1 Cancelled e = Job was cancelled
2025-01-06 17:36:53.094 1752-2407 yang com.example.myapplication I Job2 Cancelled e = Job was cancelled
- 在
IO
线程创建一个协程作用域CoroutineScope(Dispatchers.IO)
依次启动两个协程任务,主线程在500ms
后取消整个协程作用域,其中的两个协程任务都会取消
- 主线程在取消协程作用域
mScope.cancel()
之后,其中两个Job
的Start
语句会执行,End
语句不会执行,因为取消协程作用域时,两个Job都抛出了异常
取消没有返回值的协程任务Job
withContext
挂起函数检测取消信号
kotlin
复制代码
Log.i("yang", "Main Start")
val mJob = CoroutineScope(Dispatchers.IO).launch {
try {
Log.i("yang", "IO Start")
Thread.sleep(1000) // 模拟耗时任务
Log.i("yang", "IO End")
withContext(Dispatchers.Main) {
Log.i("yang", "Main withContext Start")
}
} catch (e: Exception) {
Log.i("yang", "Launch Exception = ${e.message}")
}
}
Log.i("yang", "Main Continue")
Thread.sleep(500)
mJob.cancel()
Log.i("yang", "Main End")
// log
2025-01-06 16:13:46.784 29337-29337 yang com.example.myapplication I Main Start
2025-01-06 16:13:46.785 29337-29337 yang com.example.myapplication I Main Continue
2025-01-06 16:13:46.785 29337-29622 yang com.example.myapplication I IO Start
2025-01-06 16:13:47.285 29337-29337 yang com.example.myapplication I Main End
2025-01-06 16:13:47.785 29337-29622 yang com.example.myapplication I IO End
2025-01-06 16:13:47.785 29337-29622 yang com.example.myapplication I Launch Exception = StandaloneCoroutine was cancelled
- 在
IO
线程创建一个协程作用域CoroutineScope(Dispatchers.IO)
并调用launch
方法返回一个Job
对象
主线程在500ms
后取消这个协程,但是协程体并不能立即感知自己被取消了,只会执行到withContext
才会检测取消信号
IO
线程上的所有log都会执行,withContext
挂起函数之后的代码不再执行
delay
挂起函数检测取消信号
kotlin
复制代码
Log.i("yang", "Main Start")
val mJob = CoroutineScope(Dispatchers.IO).launch {
try {
Log.i("yang", "IO Start")
delay(1000)
Log.i("yang", "IO End")
} catch (e: Exception) {
Log.i("yang", "Launch Exception = ${e.message}")
}
}
Log.i("yang", "Main Continue")
Thread.sleep(500)
mJob.cancel()
Log.i("yang", "Main End")
// log
2025-01-06 16:35:38.555 29643-29643 yang com.example.myapplication I Main Start
2025-01-06 16:35:38.558 29643-29643 yang com.example.myapplication I Main Continue
2025-01-06 16:35:38.559 29643-30198 yang com.example.myapplication I IO Start
2025-01-06 16:35:39.059 29643-29643 yang com.example.myapplication I Main End
2025-01-06 16:35:39.060 29643-30200 yang com.example.myapplication I Launch Exception = StandaloneCoroutine was cancelled
- 在
IO
线程创建一个协程作用域CoroutineScope(Dispatchers.IO)
并调用launch
方法返回一个Job
对象
主线程在500ms
后取消这个协程,但是协程体并不能立即感知自己被取消了,只会执行到delay
才会检测取消信号
IO
线程上只有IO Start
这一句Log
会执行,delay
挂起函数后的代码不再执行
CoroutineScope.isActive
变量检测取消信号
kotlin
复制代码
Log.i("yang", "Main Start")
var mJob = CoroutineScope(Dispatchers.IO).launch {
try {
Log.i("yang", "IO Start")
Thread.sleep(1000)
if (!isActive){
Log.i("yang", "IO is not active")
return@launch
}
Log.i("yang", "IO End")
} catch (e: Exception) {
Log.i("yang", "Launch Exception = ${e.message}")
}
}
Log.i("yang", "Main Continue")
Thread.sleep(500)
mJob.cancel()
Log.i("yang", "Main End")
Log.i("yang", "Main Continue")
Thread.sleep(500)
mJob.cancel()
Log.i("yang", "Main End")
// log
2025-01-06 16:48:17.754 30216-30216 yang com.example.myapplication I Main Start
2025-01-06 16:48:17.757 30216-30216 yang com.example.myapplication I Main Continue
2025-01-06 16:48:17.757 30216-30670 yang com.example.myapplication I IO Start
2025-01-06 16:48:18.257 30216-30216 yang com.example.myapplication I Main End
2025-01-06 16:48:18.758 30216-30670 yang com.example.myapplication I IO is not active
- 在
IO
线程创建一个协程作用域CoroutineScope(Dispatchers.IO)
并调用launch
方法返回一个Job
对象
主线程在500ms
后取消这个协程,但是协程体并不能立即感知自己被取消了,只会执行到!isActive
才会检测取消信号,提前return
IO
线程上只有IO Start
这一句Log
会执行,!isActive
后的代码不再执行
CoroutineScope.ensureActive()
函数检测取消信号
kotlin
复制代码
Log.i("yang", "Main Start")
var mJob = CoroutineScope(Dispatchers.IO).launch {
try {
Log.i("yang", "IO Start")
Thread.sleep(1000)
ensureActive()
Log.i("yang", "IO End")
} catch (e: Exception) {
Log.i("yang", "Launch Exception = ${e.message}")
}
}
Log.i("yang", "Main Continue")
Thread.sleep(500)
mJob.cancel()
Log.i("yang", "Main End")
// log
2025-01-06 17:17:36.781 31763-31763 yang com.example.myapplication I Main Start
2025-01-06 17:17:36.784 31763-31763 yang com.example.myapplication I Main Continue
2025-01-06 17:17:36.785 31763-32227 yang com.example.myapplication I IO Start
2025-01-06 17:17:37.285 31763-31763 yang com.example.myapplication I Main End
2025-01-06 17:17:37.785 31763-32227 yang com.example.myapplication I Launch Exception = StandaloneCoroutine was cancelled
- 在
IO
线程创建一个协程作用域CoroutineScope(Dispatchers.IO)
并调用launch
方法返回一个Job
对象
主线程在500ms
后取消这个协程,但是协程体并不能立即感知自己被取消了,只会执行到ensureActive()
才会检测取消信号
IO
线程上只有IO Start
这一句Log
会执行,ensureActive()
后的代码不再执行
取消有返回值的协程任务Deferred
- 取消有返回值的协程任务
Deferred
可以复用取消没有返回值的协程任务Job
的取消方式
- 取消整个协程作用域,也会同时取消其中启动的有返回值的协程任务
Deferred