如何使用async/await编写一个包含多个缓慢步骤的慢后台任务。

huangapple go评论58阅读模式
英文:

How to code a slow background task made of of several slow steps using async / await

问题

以下是翻译的部分:

第一个方法:
这是第一个方法的代码,其中有一个后台任务,其中包含多个需要按顺序处理的慢步骤。我尝试理解在Swift中以下两种方法之间是否存在任何区别。

第一种方法:

import SwiftUI

struct ContentView: View {
    var body: some View {
        Button("开始慢速任务") {
            Task.detached(priority: .background) {
                await slowBackgroundTask()
            }
        }
    }
}

func slowBackgroundTask() async {
    slowStep1()
    slowStep2()
    slowStep3()
}

func slowStep1() {
    // 需要很长时间
}

func slowStep2() {
    // 需要很长时间
}

func slowStep3() {
    // 需要很长时间
}

第二种方法:
第二种方法是相同的ContentView,但将函数更改如下。

func slowBackgroundTask() async {
    await slowStep1()
    await slowStep2()
    await slowStep3()
}

func slowStep1() async {
    // 需要很长时间
}

func slowStep2() async {
    // 需要很长时间
}

func slowStep3() async {
    // 需要很长时间
}

这两种模式之间有区别吗?我将非常感激能更好地理解这一点。

这两个版本都可以构建和运行。我正在尝试理解它们之间的差异。

英文:

I have a background task that has several slow steps to be processed in sequence. I am trying to understand any difference between the following two approaches in Swift.

First approach:

import SwiftUI

struct ContentView: View {
    var body: some View {
        Button("Start Slow Task") {
            Task.detached(priority: .background) {
                await slowBackgroundTask()
            }
        }
    }
}


func slowBackgroundTask() async {
    slowStep1()
    slowStep2()
    slowStep3()
}

func slowStep1() {
    // takes a long time
}

func slowStep2() {
    // takes a long time
}

func slowStep3() {
    // takes a long time
}

Approach 2 is the same ContentView, but with the functions changed as follows.

func slowBackgroundTask() async {
    await slowStep1()
    await slowStep2()
    await slowStep3()
}

func slowStep1() async {
    // takes a long time
}

func slowStep2() async {
    // takes a long time
}

func slowStep3() async {
    // takes a long time
}


Is there any difference between these two patterns? I would be most grateful to understand this better.

Both versions build and run. I am trying to understand the difference.

答案1

得分: 1

关于这两种模式之间的区别,它们都会依次运行这三个慢步骤。这两者之间有一些非常微小的差异,但很可能没有明显的区别。我更倾向于第一个代码片段,因为在任务之间切换较少,但几乎肯定不会有太大关系。

对于你的代码部分,我不会提供翻译,只会提供翻译好的文本。如果你需要对特定代码部分进行翻译,请提供代码,并我将为你提供翻译。

英文:

Regarding the difference between these two patterns, they both will run the three slow steps sequentially. There are some very modest differences between the two, but likely nothing observable. I’d lean towards the first snippet, as there are fewer switches between tasks, but it almost certainly doesn’t matter too much.


FWIW, one would generally only mark a function as async if it is actually is asynchronous, i.e., if it has an await suspension point somewhere inside it. As The Swift Programming Language says,

> An asynchronous function or asynchronous method is a special kind of function or method that can be suspended while it’s partway through execution.

But merely adding async qualifiers to synchronous functions has no material impact on their underlying synchronous behavior.

Now, if you are looking for a real performance improvement, the question is whether you might benefit from parallel execution (which neither of the snippets in the question can achieve). It depends upon a number of considerations:

  1. Are the subtasks actually independent of each other? Or is subtask 1 dependent upon the results of subtask 2? Etc.

  2. Are these subtasks trying to interact some some shared resource? Or is there going to be resource contention as you synchronize interaction with that shared resource?

  3. Is there actually enough work being done in each subtask to justify the (admittedly very modest) overhead of parallel execution? If the subtasks are not sufficiently computationally intensive, introducing parallelism can actually make it slower.

But, if answering the above questions, you conclude that you do want to attempt parallelism, that begs the question as to how you might do that. You could use async let. Or you could use a “task group”. Or you could just make three independent detached tasks. There are a number of ways of tackling it. We would probably want to know more about these three subtasks to advise you further.


As a final, preemptive, observation as you consider parallel execution, please note that the iOS simulators suffer from artificially constrained “cooperative thread pools”. E.g., see https://stackoverflow.com/q/67978028/1271826. In short, when testing parallel execution in Swift concurrency, it is best to test on a physical device, not a simulator.

huangapple
  • 本文由 发表于 2023年2月16日 11:27:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/75467559.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定