首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

如果直接在协程块中调用,为什么`async`不继承SupervisorJob?

在协程中使用async关键字时,它默认不会继承SupervisorJob。这是因为SupervisorJob是一种特殊的Job,用于创建一个可以监控和管理子协程的层次结构。当一个协程被标记为async时,它实际上是一个Deferred对象,而不是一个Job对象。

Deferred对象表示一个异步操作的结果,它可以通过await关键字来等待其完成。与Job对象不同,Deferred对象没有层次结构,因此不需要继承SupervisorJob

在协程块中调用async函数时,它将返回一个Deferred对象,该对象可以用于等待异步操作的结果。由于Deferred对象不继承SupervisorJob,因此在协程块中调用async函数不会创建一个新的协程层次结构,也不会受到SupervisorJob的监控和管理。

这种设计决策是为了保持协程的简洁性和灵活性。如果需要在协程中使用SupervisorJob来监控和管理子协程,可以手动创建一个SupervisorJob对象,并将其作为参数传递给async函数,以创建一个新的协程层次结构。

需要注意的是,以上答案是基于Kotlin协程的理解,Kotlin协程是一种轻量级的并发编程框架,用于简化异步操作的编写和管理。在其他编程语言或框架中,可能存在不同的实现和设计决策。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

Kotlin | 关于异常处理,你想知道的都在这里

引言 关于的异常处理,一以来都不是一个简单问题。...asyncA.await() asyncB.await() } } 但如果 async 其对应的不是根(即不是 scope直接.async ),则会先将异常传递给父,从而导致异常没有在调用处暴漏...如果此时我们为其增加 SupervisorJob() ,则标志着其不会主动传递异常,而是由该自行处理。所以我们可以在调用处(await()) 捕获。...---- 相关扩展 supervisorScope 官方解释如下: 使用 SupervisorJob 创建一个 CoroutineScope 并使用此范围调用指定的挂起。...提供的作用域从外部作用域继承其coroutineContext ,但用 SupervisorJob 覆盖上下文的 Job 。一旦给定及其所有子完成,此函数就会返回。

85420

再谈程之异常到底怎么办

借助这样的树形结构,可以很容易的控制结构化并发,父可以控制子的生命周期,而子可以从父继承上下文。...清理 通常, 当被取消时, 需要做一些清理工作, 此时, 可以把运行的代码用try {} fininaly {}包住, 这样当被取消时, 会执行fininaly的清理工作。...但是fininaly不能直接调用挂起函数,否则会抛出CancellationException异常,因为它已经被取消了,而你又要在fininaly执行挂起函数把它挂起,显然与要求矛盾。...方法 ❝如果调用Join后再调用cancel,那么将在执行完成后被Cancel,如果先cancel再调用Join,那么也将执行完成 ❞ 异常的处理 当作用域中的一个发生异常时,此时的异常流程如下所示...asyncasync的异常处理比较麻烦,我们下面详细的说下。 首先,当async被用作构建根(由作用域直接管理的)时,异常不会主动抛出,而是在调用.await()时抛出。

68310
  • 的取消和异常 | 异常处理详解

    async 被用作根 (CoroutineScope 实例或 supervisorScope 的直接子) 时不会自动抛出异常,而是在您调用 .await() 时才会抛出异常。...这就是为什么没有必要将它也包裹进 try/catch ,await 将会抛出 async 中产生的所有异常。...当 async 被用作根时,异常将会在您调用 .await 方法时被抛出 另一个需要注意的地方是,这里使用了 supervisorScope 来调用 async 和 await。...正如我们之前提到的,SupervisorJob 会让自己处理异常;而相对的,Job 则会在层级间自动传播异常,这样一来 catch 部分的代码就不会被调用: coroutineScope {...,而不会调用 .await() } } 本例,由于 scope 的直接子是 launch,如果 async 中产生了一个异常,这个异常将就会被立即抛出。

    1.1K20

    如何正确的在 Android 上使用

    在 Android ,一般是建议直接使用 GlobalScope 的。那么,在 Android 应该如何正确使用呢?再细分一点,如何直接在 Activity 中使用呢?...这两点,也正是使用中所需要注意的。既然建议直接使用 GlobalScope,我们就先试验一下使用它会是什么效果。...直接使用 GlobalScope 的 async 或者 launch 方法是强烈建议的。 GlobalScope 创建的没有父,GlobalScope 通常也不与任何生命周期组件绑定。...() {} 通过扩展函数 launch() 可以直接在主线程启动,示例代码如下: private fun launchFromMainScope() { launch {...添加如下依赖: implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0-alpha03" 直接在 liveData {} 代码调用需要异步执行的挂起函数

    2.8K30

    kotlin 入门教程

    为什么直接使用Java线程池 这里需要提前说明一下,kotlin 封装的线程池与 java 的线程池是不一样的。...它内部的线程数量一般会更多一些 Dispatchers.Unconfined,对执行的线程不做限制,可以直接在当前调度器所在线程上执行 Dispatchers.Main,在Android,表示UI...这是因为它们会自动检测当前是否已经被取消了,如果已经被取消了,就会抛出 CancellationException 异常,从而终止当前的异常的传播 之前讲过存在父子结构。...如果想要子1发生异常时,不影响其他的,可以使用 SupervisorJob。...如果使用了SupervisorJob(),1和 parentJob 就不是父子结构了,这时虽然1抛出异常,由于不是父子关系了就不会影响其他,但是同时parentJob.cancel 和 join

    18410

    抽丝剥茧Kotlin -

    如果你会使用,那你肯定知道中有 CoroutineScope、CoroutineContext 和 CoroutineDispatcher,这些都是使用过程我们可以接触到的 API。...Continuation 如果你会使用,那你肯定知道,遇到耗时 suspend 操作可以挂起,等到任务结束的时候,会自动切回来。...从上面的类的机构可以看出,光看这个 CoroutineContext 这个接口(源码内容我们下面讲),会发现它有点像 List 集合,而继承自 CoroutineContext 接口的 Element...该方法会去执行 launch 包裹的代码,并返回一个结果。 将上述代码执行的结果交给 completion,由它完成结束的通知。...不过我们 suspend 修饰的外层 Continuation 还没有创建,它来了,是 SuspendLambda,它继承自 ContinuationImpl,如果你问我为什么源码没找到具体实现,我觉得可能跟

    81930

    Coroutines : First things first

    这是关于 的取消和异常 的一系列文章,写的很不错。一准备翻译来着,种种原因给耽误了,一拖到现在。...正在运行的可以通过调用 scope.cancel() 在任意时间点停止。 无论你在 App 的任何页面启动,并控制其生命周期,都应该创建 CoroutineScope 。...关于 Parent CoroutineContext 在继承结构,每一个都会有一个父亲,这个父亲可能是 CoroutineScope 或者另一个。...在系列第三篇文章我们将看到,CoroutineScope 可以拥有其他的 Job 实现类,SupervisorJob ,它会改变作用域的异常处理。...因此,在这样的 CoroutineScope 创建的子也将继承 SupervisorJob 类型的 Job 。但是,如果当父是另一个的时候,将总是 Job 类型。

    65130

    Kotlin上下文和异常处理

    剩下的元素会从CoroutineContext的父类继承,该父类可能是另外一个或者创建该的CoroutineScope 的上下文 = 默认值 + 继承的CoroutineContext +...(async和produce) 当这些构建器用于创建一个根时(该不是另一个的子),前者这类构建器异常发生时会第一时间被抛出,而后者则依赖用户来最终消费异常,例如通过调用await或receive...接下来父级会进行下面几步操作: 取消它自己的子级 取消它自己 将异常传播并传递给它的父级 SupervisorJob和SupervisorScope 使用SupervisorJob时,一个子的运行失败不会影响其他的子...,SupervisorJob不会传播异常给它的父级,它会让子自己处理异常 或者SupervisorScope的子,一个失败,其他的子也不会受影响,但如果作用域里面有异常失败,则所有子都会失败退出...的CoroutineContext或在一个根(CoroutineScope或者supervisorScope的直接子 handler要安装在外部,不能在内部,否则捕获不到异常

    7410

    的取消和异常 | 驻留任务详解

    的最佳实践 由于本文所介绍的模式是在的其它最佳实践的基础之上实现的,我们可以借此机会回顾一下: 1. 将调度器注入到类 不要在创建调用 withContext 时硬编码调度器。...我们需要在 Application 类创建自己的作用域,并在由它启动的调用这些操作。这个作用域应当被注入到那些需要它的类。...applicationScope 必须包含一个 SupervisorJob(),这样的故障便不会在层级间传播 (见本系列第三篇文章: 的取消和异常 | 异常处理详解): class MyApplication...您需要基于 veryImportantOperation 的行为来使用 launch 或 async 启动新的: 如果需要返回结果,请使用 async调用 await 来等待其完成; 如果不是,...{ // 异常会在调用 await 时暴露,它们会在调用了 doWork 的传播。

    1.4K20

    关于 Kotlin Coroutines, 你可能会犯的 7 个错误

    另外由于构建器 launch{} 和 async{} 都需要 job 作为入参,你可能会想到创建一个新的 job 实例作为参数来使用。...CoroutineScope 运行这个协,然后取消协作用域而不是的 job 。...为什么会这样? 原来,为了让异步/同步代码更加安全,提供了革命性的特性 —— “结构化并发” 。“结构化并发” 的一个机制就是:当作用域被取消时,就取消该作用域中的所有。...错误的使用 SupervisorJob 有时候你会使用 SupervisorJob 来达到下面的效果: 在 job 继承体系停止异常向上传播 当一个失败时不影响其他的同级 由于构建器 launch...{} 和 async{} 都可以传递 Job 作为入参,所以你可以考虑向构建器传递 SupervisorJob 实例。

    95520

    【Kotlin 启动 ④ ( 启动模式 | 构建器启动模式参数 | DEFAULT 模式 | ATOMIC 模式 | LAZY 模式 | UNDISPATCHED 模式 )

    一、构建器 CoroutineScope.async 函数 ---- 1、构建器 CoroutineScope.async 函数参数分析 构建器 CoroutineScope.async 函数....() -> T 是作用域代码 , 其中是任务代码 ; 2、构建器 CoroutineScope.async 函数参数原型 CoroutineScope.async 函数原型 : 机翻文档..., 才在子线程执行挂起函数 ; 如果在主线程启动 , 则该模式的就会直接在主线程执行 ; 如果在子线程启动 , 则该模式的就会直接在子线程执行 ; 代码示例 : Dispatchers.IO...调度器是将调度到子线程执行 , 但是如果 启动模式为 UNDISPATCHED , 则 立刻在当前的主线程执行 , 创建后 , 立即在当前的 函数调用栈 执行任务 , 打印当前线程时...// 创建后 , 立即在当前的 函数调用栈 执行任务 , // 直到遇到第一个挂起函数 , 才在子线程执行挂起函数 ; val job = async ( context

    1K10

    揭秘kotlin的CoroutineContext

    ] 当一个创建后它就处于新建(New)状态,当调用Job的start/join方法后就处于活跃(Active)状态,这是运行状态,运行出错或者调用Job的cancel方法都会将当前置为取消...中有两种类型的Job,如果我们平时启动时没有特意地通过CoroutineContext指定一个Job,那么使用launch/async方法启动时返回的Job它会产生异常传播,我们知道有一个父子的概念...yield方法时,Unconfined的dispatch方法才会被调用,yield方法是一个suspend方法,当在调用这个方法时表示当前让出自己所在的线程给其他运行,所以正常情况下是不会调用...Unconfined任务,就暂时把它放进跟当前线程关联的EventLoop,等待执行,同时Unconfined任务里面会调用Continuation的resumeWith方法恢复运行,这也是为什么指定了...,而对async启动的根无效,因为async启动的根默认会捕获所有未捕获异常并把它放在Deferred,等到用户调用Deferred的await方法才抛出,如下: fun main(){

    1.9K30

    kotlin--上下文、异常处理

    构造了新的上下文 4.coroutineScope:继承的父上下文,不能算是全新的 等等 3.子继承时,除了Job会自动创建新的实例外,其他3项的手动指定的话,都会自动继承的...(主线程的,手动调用jobA的join方法,那么主线程就会阻塞,直到jobA执行完毕。...,也不会影响上下文继承关系,主还是会等待子执行完毕后才结束生命 如果你已经完全理解了,那么就可以知道以上例子使用async启动也是一样的效果 二、的异常传递 1.的异常传播也是遵循了上下文的机制...async启动,哈哈,这就奇怪了,为什么会这样?...)的 三、的异常处理 1.如果想要一个出现异常后,不影响其继承关系的其他,可以使用SupervisorJob fun `test SupervisorJob exception`()

    93610

    的取消和异常 | 核心概念介绍

    任何时候都可通过调用 scope.cancel() 来取消正在进行的工作 (正在运行的)。...对于每一个您所创建的 (通过 launch 或者 async),它会返回一个 Job 实例,该实例是的唯一标识,并且负责管理的生命周期。...△ Job 的生命周期 如果处于活跃状态,运行出错或者调用 job.cancel() 都会将当前任务置为取消 (Cancelling) 状态 (isActive = false, isCancelled...在我们这个系列的第三部分,CoroutineScope 会有另外一个 Job 的实现称为 SupervisorJob 被包含在其 CoroutineContext ,该对象改变了 CoroutineScope...因此,由该 scope 对象创建的新会将一个 SupervisorJob 作为其父级 Job。不过,当一个的父级是另外一个时,父级的 Job 会仍然是 Job 类型。

    1K10

    Kotlin 学习笔记(四)—— 的基础知识,面试官的最爱了~

    所以,suspend 关键字更多的是给调用者一个提示,提示调用者被它修饰的方法是个耗时方法,需要在或者其他 suspend 函数处理,限制这个方法只能在或其他 suspend 函数中被调用。...这也是为什么我们可以在中用写同步代码的思想,去写异步的逻辑。...再来看下不同的启动模式,有四种: DEFAULT:默认值,表示创建后,立即开始调度,在执行前如果被取消则直接进入取消响应状态; LAZY:表示该只有主动调用的 start 或 join 或...; UNDISPATCHED:表示创建后立即在当前函数调用执行,是运行在创建时所在的线程。...3.4 作用域 launch 函数的第三个参数是一个由外层 CoroutineScope 调用的 lambda 闭包,我们需要在处理的逻辑都在这个闭包实现。

    1.5K30

    kotlin-的异常处理机制分析

    ),然后给下面创建用,具体逻辑下面代码分析 val newContext = newCoroutineContext(context) //这里就是创建 val coroutine...,job2所在的发生异常,不会把job取消(会打印“4”),而且异常是job2所在抛出来的 3、异常处理的流程源码分析 3.1、的三层包装 第一层:launch和async返回的job...,封装了的状态,提供取消协的接口,实例都是继承自AbstractCoroutine 第二层:编译器生成(cps)的SuspendLambda的子类,封装了的真正运算逻辑,继承自BaseContinuationImpl...如果发生异常即notifyRootCause不为空的时候,调用notifyCancelling方法,主要是取消子 private fun notifyCancelling(list: NodeList...= null) { //异常的传递和处理逻辑,如果cancelParent(finalException)处理异常的话,就由当前 //处理handleJobException

    93330
    领券