当前位置:网站首页>The kotlin coroutine -- coroutine context and exception propagation
The kotlin coroutine -- coroutine context and exception propagation
2022-06-12 21:52:00 【Laysm0507】
In the process of execution , You can cancel a collaboration by canceling the scope of the collaboration , In this case, an exception will be thrown , But it has been dealt with silently , Therefore, the user has no perception
Collaboration context
1 Non cancellable tasks
stay kotlin in , All pending functions withContext、delay etc. , All can be cancelled , But like CPU Intensive task , It can't be cancelled , For example, circulation
var i = 0
val job = viewModelScope.launch {
// Judge here Job Life cycle of
while (i < 5 /* && isActive ensureActive*/) {
i += 1
delay(1000)
Log.e("TAG", "index ---- $i++")
}
}
delay(2000)
Log.e("TAG", " I'm going to cancel ")
job.cancelAndJoin()
If you want to cancel CPU Intensive task , Because it's executing Job Of cancel After method ,isActive Property is to change to false, Then you can judge isActive perhaps ensureActive Come on break loop
2 Collaboration context
public fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job {
val newContext = newCoroutineContext(context)
val coroutine = if (start.isLazy)
LazyStandaloneCoroutine(newContext, block) else
StandaloneCoroutine(newContext, active = true)
coroutine.start(start, coroutine, block)
return coroutine
}
In the scope of building collaboration , The first parameter is the coroutine context CoroutineContext, The default is EmptyCoroutineContext
2.1 Composition of collaborative process context
The coroutine context is defined by Job,Dispatchers,CorotinueName,CorotinueExceptionHandler form , among Job Used to control the life cycle of the collaborative process ,Dispatchers The thread used to allocate the execution of the coprocessor ,CorotinueName The name of Xie Cheng , When debugging , You can view the status of the target collaboration ,CorotinueExceptionHandler Used to catch exceptions in the process
val job = viewModelScope.launch(Dispatchers.IO + Job() + CoroutineName("test") ) {
Log.e("TAG","${
coroutineContext}")
}
Print :[CoroutineName(test), StandaloneCoroutine{
Active}@6f35b52, Dispatchers.IO]
2.2 Inheritance of coroutine context
Creation of subprocesses , It will create a new one Job object , Other images Dispatchers,CorotinueName, Will inherit from the parent process
val job = viewModelScope.launch(Dispatchers.IO + Job() + CoroutineName("test") ) {
Log.e("TAG","${
coroutineContext}")
// Zixie Cheng
launch {
Log.e("TAG","${
coroutineContext}")
}
}
Print : [CoroutineName(test), StandaloneCoroutine{
Active}@6f35b52, Dispatchers.IO]
[CoroutineName(test), StandaloneCoroutine{
Active}@edd0e23, Dispatchers.IO]
It can be seen that , except Job Different objects , Others are consistent with the parent process , If a new context is declared in the subprocess , Then it will cover
val job = viewModelScope.launch(Dispatchers.IO + Job() + CoroutineName("test") ) {
Log.e("TAG","${
coroutineContext}")
// The subprocess declares a new Dispatchers
launch (Dispatchers.Main){
Log.e("TAG","${
coroutineContext}")
}
}
Print : [CoroutineName(test), StandaloneCoroutine{
Active}@6f35b52, Dispatchers.IO]
[CoroutineName(test), StandaloneCoroutine{
Active}@edd0e23, Dispatchers.Main]
3 Abnormal propagation
When an exception occurs in the coordination process , The cancellation exception introduced before is handled silently , But if you throw other exceptions , You need to handle the exception manually
3.1 launch and async Exception capture
launch and async Is the key to creating a collaborative process 2 Ways of planting , image launch The created process , Exceptions are propagated automatically , As long as an exception occurs , Will be thrown the first time ; and async It belongs to user consumption exception , Only the user calls await To throw an exception
therefore ,launch and async It's different when catching exceptions ,launch You need to catch exceptions in the process body , and async Need to call await When , To catch exceptions
viewModelScope.launch(Dispatchers.IO + Job() + CoroutineName("test") ) {
print(123)
throw ArrayIndexOutOfBoundsException()
}
The way to catch exceptions
viewModelScope.launch(Dispatchers.IO + Job() + CoroutineName("test") ) {
try {
print(123)
throw ArrayIndexOutOfBoundsException()
}catch (e:Exception){
if(e is ArrayIndexOutOfBoundsException){
Log.e("TAG"," The array is out of bounds ")
}
}finally {
}
}
Above is launch Collaboration created by , If it is async The created process , It's impossible to catch exceptions in the process body
val job = viewModelScope.async {
delay(500)
throw IOException()
}
job.await()
The way to catch exceptions
val job = viewModelScope.async {
delay(500)
throw IOException()
}
try {
job.await()
}catch (e:IOException){
Log.e("TAG"," Exception caught ")
}
Of course , The current treatment is in the root process , If it is in the subprocess , Whether it's launch still async Will throw an exception directly ,async No need await
viewModelScope.launch(Dispatchers.IO + Job() + CoroutineName("test") ) {
// here try - catch I can't see this anomaly
async {
delay(500)
throw ArrayIndexOutOfBoundsException()
}
}
It's not called here await, An exception is thrown directly , This is in the subprocess
3.2 Propagation characteristics of CO process
When an exception occurs in the subprocess , First of all, they will report to their parents , The parent process cancels all its child processes , Then cancel yourself , Report the exception to your parent process
In the process , adopt try-catch You can't catch exceptions , Exceptions will still be thrown and reported to the parent process , The parent process will cancel all these processes , This is it. launch and async An exception that cannot be caught , If you want to catch these exceptions , You have to use... In the context of collaboration CorotinueExceptionHandler
val handler = CoroutineExceptionHandler {
_, throwable ->
// Abnormal aggregation The exception handled will be attached to the previous exception
Log.e("TAG"," Exception caught ---- ${
throwable.cause}")
}
viewModelScope.launch(Dispatchers.IO + Job() + CoroutineName("test") + handler ) {
try {
launch {
delay(500)
throw ArrayIndexOutOfBoundsException()
}
}catch (e:Exception){
}
}
Like an exception thrown in a subprocess , If not CoroutineExceptionHandler, Then all word associations will be cancelled , And then add CoroutineExceptionHandler Can catch this exception , And it won't cancel all the sub processes
In addition to the above way , Can pass SupervisorJob Create a collaboration scope or use supervisorScope Create collaboration scope , I've tried this way , It seems that the parent association process should be cancelled , I was in ViewModel Used in , You can try it yourself in private
边栏推荐
猜你喜欢

SQL tuning guide notes 15:controlling the use of optimizer statistics

User guide for JUC concurrency Toolkit

Graphics2D类基本使用

SQL调优指南笔记14:Managing Extended Statistics

The ifeq, filter and strip of makefile are easy to use

Npoi create word

Experiment 7-2-6 print Yanghui triangle (20 points)

JVisualVM初步使用

SQL tuning guide notes 9:joins

Producer consumer model under multithreading model
随机推荐
My struggle: my years in foreign enterprises (1)
数据批量写入
Economist focuses on WTO MC12: digital economy may become an important issue
【QNX Hypervisor 2.2 用户手册】4.4 构建Host
DRF receives nested data and creates objects. Solution: DRF not NULL constraint failed
建立高可用的数据库
2021 rust survey results released: 9354 questionnaires collected
How to ensure thread safety?
Exception encountered by selenium operation element
gzip压缩解压缩
“Oracle数据库并行执行”技术白皮书读书笔记
动态规划之如何将问题抽象转化为0-1背包问题(详解利用动态规划求方案数)
SQL tuning guide notes 14:managing extended statistics
How to abstract a problem into a 0-1 knapsack problem in dynamic programming
Kdd2022 | graphmae: self supervised mask map self encoder
SQL调优指南笔记14:Managing Extended Statistics
PE installation win10 system
Oracle SQL Developer的代码输入框中推荐使用的中文字体
What is the difference between volatile variables and atomic variables?
Thread safe level