首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >异步内部的withContext

异步内部的withContext
EN

Stack Overflow用户
提问于 2022-02-26 00:33:36
回答 2查看 340关注 0票数 2

我已经有两个长期运行的任务,每个任务都封装在withContext中。但是现在我想并行运行它们,等待它们的结果。因此,我想知道我是否像下面这样使用它们(用异步封装它们):

代码语言:javascript
复制
    val result1 = async { 
      withContext(Dispatcher.IO) { 
        someLongRunningBackgroundWork1...
        ....
      } 
    }

    val 2 = withContext(Dispatcher.IO) { 
        someLongRunningBackgroundWork2...
        ....
      } 
    }

这个很好用。但我想知道这场戏背后有没有什么取舍?

EN

回答 2

Stack Overflow用户

发布于 2022-02-27 02:48:26

async(Dispatchers.IO) { /*...*/ }是与async { withContext(Dispatchers.IO) { /*...*/} }相同的逻辑。在任何一种情况下,不明确的异常都会导致async失败。如果在coroutine中使用这样的裸async调用,那么它就是一个子协同,异常将被传播到父进程。如果在特定的async上调用了CoroutineScope,那么它不是子协同器,除非调用await()join(),否则不会传播它的异常。通常,当您希望在协同线中运行一些并行任务,然后继续运行时,可以将它们封装在一个coroutineScope调用中。

你可以在你的协同线上做这样的事情来分解平行的工作。在coroutineScope内部抛出的任何不正常异常都会在其外部重新抛出,并将取消coroutineScope中任何未运行的子协同。

代码语言:javascript
复制
val (result1, result2) = coroutineScope {
    val result1 = async(Dispatcher.IO) { 
        //someLongRunningBackgroundWork1...
        //....
    }

    val result2 = withContext(Dispatcher.IO) { 
        //someLongRunningBackgroundWork2...
        //....
    } 
    result1.await() to result2
}

与现在相比,它的优点是,如果任何一个代码块失败,其他并行任务将自动被取消。

票数 2
EN

Stack Overflow用户

发布于 2022-02-27 06:36:31

正如您在注释中所说的,您的函数使用withContext(IO),您不想改变这一点。将它们封装在async中将首先启动当前调度程序中的协同线(如果您使用的是Main),然后立即切换到IO。虽然不会花很多钱,但还是没有必要。如果您将函数包装在async(IO)中,协同线将直接在正确的调度程序上启动,而内部的withContext(IO) { }基本上是不操作的。

正如Tenfour04提出的,启动背景工作并等待其结果应该包含在一个单一的工作单元中,一旦其任何部分失败,该单元就会立即失败。您不会显示在已启动的协同线上调用await()的位置,但通常asyncawait语句都应该发生在同一个coroutineScope块中。当该块结束时,您可以保证在后台不再有正在进行的工作,如果任何其他并发子任务(或主要任务)失败,还可以通过取消它来节省时间和资源。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71273107

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档