Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 等待任务完成_Swift_Multithreading_Asynchronous_Swift3_Grand Central Dispatch - Fatal编程技术网

Swift 等待任务完成

Swift 等待任务完成,swift,multithreading,asynchronous,swift3,grand-central-dispatch,Swift,Multithreading,Asynchronous,Swift3,Grand Central Dispatch,如何使代码等待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 cont

如何使代码等待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编写。

使用调度组

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.

使用
DispatchGroup
s来实现这一点。您可以在组的
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() gets run 
    // 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()
阻塞当前队列(在您的情况下可能是主队列),因此您必须在另一个队列上
调度.async
(如上面的示例代码中),以避免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)")
最后一件事:如果要在任务使用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
}

Swift 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!)
        }
    }
}

解决方案的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)") 
}

假设您在主队列上调用此函数,这将导致死锁。@Shallow尽管如此。我想在另一个类中执行一个函数,但我想等待该函数完成,然后在当前类中继续执行,我如何处理它?尽管上面的示例将在主线程上阻塞,如前面的答案所示,在
DispatchQueue.global().async{}
中包装不会阻止主队列。我想在另一个类中执行函数,但我想等待完成该函数,然后在当前类中继续。我如何处理该问题?@saeedrahmotolahi:或者使用
等待
方法(如果阻塞没有问题,即如果您不在主线程上)或者在调用类中提供一个完成处理程序或使用notify方法。为什么要调用
组。在异步块之外输入
?是否每个块都应该负责输入和离开组?@Bill
等待
直到
输入
离开
调用平衡。如果您输入
输入
在闭包中,
wait
不会等待,因为尚未调用
enter
,因此
enter
leave
调用的数量是平衡的(#enter==0,#leav==0).@rustyMagnet for tests这很可能不是正确的方法。请改用
xctestextexpectation
s。请看,我尝试了所有这些方法,但在for循环中处理firebase调用时,没有一个有效
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)") 
}