swift 等待任务完成

h22fl7wq  于 2022-11-21  发布在  Swift
关注(0)|答案(7)|浏览(151)

我如何让我的代码等待DispatchQueue中的任务完成?它需要任何CompletionHandler或其他什么吗?

func myFunction() {
    var a: Int?

    DispatchQueue.main.async {
        var b: Int = 3
        a = b
    }

    // wait until the task finishes, then print 

    print(a) // - this will contain nil, of course, because it
             // will execute before the code above

}

我用的是Xcode 8.2,用的是Swift 3。

dy1byipe

dy1byipe1#

使用DispatchGroup来实现这一点。当组的enter()leave()呼叫平衡时,您可以得到通知:

func myFunction() {
    var a: Int?

    let group = DispatchGroup()
    group.enter()

    DispatchQueue.main.async {
        a = 1
        group.leave()
    }

    // does not wait. But the code in notify() is executed 
    // after enter() and leave() calls are balanced

    group.notify(queue: .main) {
        print(a)
    }
}

或者您可以等待:

func myFunction() {
    var a: Int?

    let group = DispatchGroup()
    group.enter()

    // avoid deadlocks by not using .main queue here
    DispatchQueue.global(attributes: .qosDefault).async {
        a = 1
        group.leave()
    }

    // wait ...
    group.wait()
    
    print(a) // you could also `return a` here
}

注意group.wait()阻塞了当前队列(在您的示例中可能是主队列),因此您必须对另一个队列执行dispatch.async(如上面的示例代码)以避免死锁

oprakyz7

oprakyz72#

在Swift 3中,当DispatchQueue完成一个任务时,不需要完成处理程序,而且你可以通过不同的方式来实现你的目标
其中一个办法是这样的:

var a: Int?

    let queue = DispatchQueue(label: "com.app.queue")
    queue.sync {

        for  i in 0..<10 {

            print("Ⓜ️" , i)
            a = i
        }
    }

    print("After Queue \(a)")

它将等待直到循环完成,但在这种情况下,您的主线程将阻塞。
你也可以这样做:

let myGroup = DispatchGroup()
    myGroup.enter()
    //// Do your task

    myGroup.leave() //// When your task completes
     myGroup.notify(queue: DispatchQueue.main) {

        ////// do your remaining work
    }

最后一件事:如果要在使用DispatchQueue完成任务时使用completionHandler,可以使用DispatchWorkItem
下面是一个如何使用DispatchWorkItem的示例:

let workItem = DispatchWorkItem {
    // Do something
}

let queue = DispatchQueue.global()
queue.async {
    workItem.perform()
}
workItem.notify(queue: DispatchQueue.main) {
    // Here you can notify you Main thread
}
fwzugrvs

fwzugrvs3#

Swift 5版本的解决方案

func myCriticalFunction() {
    var value1: String?
    var value2: String?

    let group = DispatchGroup()

    group.enter()
    //async operation 1
    DispatchQueue.global(qos: .default).async { 
        // Network calls or some other async task
        value1 = //out of async task
        group.leave()
    }

    group.enter()
    //async operation 2
    DispatchQueue.global(qos: .default).async {
        // Network calls or some other async task
        value2 = //out of async task
        group.leave()
    }

    
    group.wait()

    print("Value1 \(value1) , Value2 \(value2)") 
}
jljoyd4f

jljoyd4f4#

使用调度组

dispatchGroup.enter()
FirstOperation(completion: { _ in
    dispatchGroup.leave()
})
dispatchGroup.enter()
SecondOperation(completion: { _ in
    dispatchGroup.leave()
})
dispatchGroup.wait() // Waits here on this thread until the two operations complete executing.
eh57zj3b

eh57zj3b5#

在Swift 5.5+中,您可以利用Swift Concurrency,它允许从分派给主线程的闭包返回值

func myFunction() async {
    var a : Int?

    a = await MainActor.run {
        let b = 3
        return b
    }

    print(a)
}

Task {
    await myFunction()
}
au9on6nz

au9on6nz6#

雨燕4

在这些情况下,您可以使用异步函数。当您使用DispatchGroup()时,有时可能会发生死锁。

var a: Int?
@objc func myFunction(completion:@escaping (Bool) -> () ) {

    DispatchQueue.main.async {
        let b: Int = 3
        a = b
        completion(true)
    }

}

override func viewDidLoad() {
    super.viewDidLoad()

    myFunction { (status) in
        if status {
            print(self.a!)
        }
    }
}
ezykj2lf

ezykj2lf7#

不知何故,上面的dispatchGroup enter()和leave()命令对我的情况不起作用。
虽然在后台线程的while循环中使用sleep(5)对我来说很有用,但我还是留了下来,以防它对其他人有帮助,并且不会干扰我的其他线程。

相关问题