将完成处理程序集中在一起,以便在执行多个闭包时完成方法 [英] Pooling completion handlers together such that method completes once multiple closures are executed

查看:17
本文介绍了将完成处理程序集中在一起,以便在执行多个闭包时完成方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个场景,我想并行执行三个不同的异步任务.完成所有三个任务后,我希望调用方法知道这一点并调用自己的完成处理程序.

I have a scenario where I want to perform three distinct asynchronous tasks in parallel. Once all three tasks are complete, I then want the calling method to be aware of this and to call its own completion handler.

下面是一个非常简化的逻辑版本:

Below is a very simplified version of the logic for this:

class ViewController: UIViewController {
    func doTasks(with object: Object, completionHandler: () -> Void) {
        // Once A, B & C are done, then perform a task
        wrapupTask()
        // When task is complete, call completionHandler
        completionHandler()
    }
}

fileprivate extension ViewController {
    func taskA(with object: Object, completionHandler: () -> Void) {
        // Do something

        completionHandler()
    }

    func taskB(with object: Object, completionHandler: () -> Void) {
        // Do something

        completionHandler()
    }

    func taskC(with object: Object, completionHandler: () -> Void) {
        // Do something

        completionHandler()
    }
}

我可以轻松地将处理程序链接在一起,但这样一来任务可能会花费更长的时间并且代码会很糟糕.

I could easily chain the handlers together, but then the task will likely take longer and the code will suck.

我考虑的另一个项目是一个简单的计数器,它在每次任务完成时递增,然后一旦达到 3,就会通过如下方式调用 wrapupTask():

Another item I considered was a simple counter that incremented each time a task completed, and then once it hit 3, would then call the wrapupTask() via something like this:

var count: Int {
   didSet {
      if count == 3 {
         wrapupTask()
      }
   }
}

我考虑过的另一个选择是创建一个操作队列,然后将任务加载到其中,并依赖于何时运行我的总结任务.一旦队列为空,它将调用完成处理程序.然而,这似乎比我想要完成的工作要多.

Another option I have considered is to create an operation queue, and to then load the tasks into it, with a dependency for when to run my wrap up task. Once the queue is empty, it will then call the completion handler. However, this seems like more work than I'd prefer for what I want to accomplish.

我希望有更好的东西我只是错过了.

My hope is that there is something better that I am just missing.

推荐答案

只是为了了解 OOPer 所说的内容,您正在寻找 DispatchGroup.在下面,对taskAtaskBtaskC的调用是伪代码,但其他一切都是真实的:

Just to pick up on what OOPer said, you are looking for DispatchGroup. In the following, the calls to taskA, taskB, and taskC are pseudo-code, but everything else is real:

func doTasks(with object: Object, completionHandler: () -> Void) {
    let group = DispatchGroup()
    group.enter()
    taskA() {
        // completion handler
        group.leave()
    }
    group.enter()
    taskB() {
        // completion handler
        group.leave()
    }
    group.enter()
    taskC() {
        // completion handler
        group.leave()
    }
    group.notify(queue: DispatchQueue.main) {
        // this won't happen until all three tasks have finished their completion handlers
        completionHandler()
    }
}

每个 enter 都与异步完成处理程序末尾的 leave 匹配,只有当所有匹配都实际执行后,我们才继续执行 通知完成处理程序.

Every enter is matched by a leave at the end of the asynchronous completion handler, and only when all the matches have actually executed do we proceed to the notify completion handler.

这篇关于将完成处理程序集中在一起,以便在执行多个闭包时完成方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆