首页
学习
活动
专区
工具
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 。一旦给定块及其所有子协程完成,此函数就会返回。

92620
  • 再谈协程之异常到底怎么办

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

    70410

    协程中的取消和异常 | 异常处理详解

    当 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

    20810

    抽丝剥茧Kotlin - 协程

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

    84930

    Coroutines : First things first

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

    65830

    Kotlin协程上下文和异常处理

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

    8810

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

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

    1.5K20

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

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

    99720

    【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

    1.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.9K31

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

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

    1K10

    kotlin--协程上下文、异常处理

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

    95510

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

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

    1.6K30

    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

    95130
    领券