【问题标题】:One method in many Tasks async/await许多任务异步/等待中的一种方法
【发布时间】:2022-02-10 20:19:47
【问题描述】:

您好,我有一种情况需要在多个任务中调用相同的方法。我希望有可能不以并行模式一一调用此方法(同步)。看起来是这样的:

var isReadyToRefresh: Bool = true

func refresh(value: Int) async {
    try! await Task.sleep(nanoseconds: 100_000_000) // imitation API CALL
    isReadyToRefresh = false
    print("Try to refresh: \(value)")
}

func mockCallAPI(value: Int) async {
    if isReadyToRefresh {
        await refresh(value: value)
    }
}

Task {
     await mockCallAPI(value: 1)
}

Task {
     await mockCallAPI(value: 2)
}

输出:

尝试刷新:1

尝试刷新:2

我需要的输出:

尝试刷新:1 或尝试刷新 2。取决于哪个任务被称为第一个任务。

有什么想法吗?

【问题讨论】:

  • 我想等待第一次刷新API完成@Rob

标签: swift async-await task grand-central-dispatch urlsession


【解决方案1】:

你说:

我希望 [第二次尝试] 等待第一次刷新 API 完成

您可以保存对您的Task 的引用,如果找到,则保存await。如果没有找到,则启动任务:

actor Refresh {
    var task: Task<Void, Never>?

    func refresh(value: Int) async {
        try! await Task.sleep(nanoseconds: 100_000_000) // imitation API CALL
        print("Try to refresh: \(value)")
    }

    func mockCallAPI(value: Int) async {
        if let task = self.task {
            _ = await task.result
            return
        }

        task = Task {
            await refresh(value: value)
            task = nil
        }
    }
}

Apple 在随 WWDC 2021 视频提供的代码 Protect mutable state with Swift actors 中展示了这种模式的示例(但此代码不在网站上;仅在开发者应用程序中提供)。见How to prevent actor reentrancy resulting in duplicative requests?

他们的例子更复杂(一种避免重复网络请求被某些图像缓存/下载器发起的模式),但想法的核心是相同的:保存和awaitTask

【讨论】:

    【解决方案2】:

    如果您不希望它们并行运行,为什么它们需要处于单独的任务中,await 意味着代码在任务完成后不会继续进行,因为启动它的线程可能是协作线程用于做其他事情,例如更多地使用交互或其他任务进行处理,实际上因为您将它们放在单独的任务中,您要求它们并行运行,因此包含它们的块可能会进入非常带和您将有另外两个任务,在这种情况下,您需要等待它们的容器任务的结果表明它们已完成,并且进入块的代码会检查它以继续进行。

    【讨论】:

    • OP 没有说明具体的场景,但是从“刷新”方法名称,我推断出一个场景,其中有两个单独的事件可以触发刷新(例如,可能是推送通知和大约在同一时间发生的用户发起的“拉动刷新”)。他可能不希望两个并发的网络请求刷新同一个资源。这是一个合理的要求,完全合乎逻辑。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-06
    • 2018-02-23
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 2014-03-18
    相关资源
    最近更新 更多