Swift 3:执行多个线程并等待finalize

时间:2017-03-08 13:05:00

标签: swift multithreading grand-central-dispatch

我试图向我的API发送迭代图像数组的多张照片。 我想在不同的线程中发送每个图像但是当第一个线程时 完成它不会等待其余的线程和只有一张图片 发了。

这是我的代码:

// create the concurrent queue
    let asyncQueue = DispatchQueue(label: "asyncQueue", attributes: .concurrent)

    // perform the task asynchronously
    for image in self.arrayImages{
        asyncQueue.async() {
            let strBase64:String = image.base64EncodedString(options: .lineLength64Characters)
            self.sendImage(image: strBase64)
        }

    }

我最近开始使用Swift编程,但我不知道如何同步线程。你能帮帮我吗?

执行我的请求的代码是:

// Función para mandar a la API la petición de añadir una imagen a la idea
func sendImage(image:String){
    let data = NSMutableDictionary()

    let id:Int = (idea?.id)!
    let pasoAct = idea?.pasoActual
    data["id_idea"] = id
    data["id_paso"] = pasoAct
    data["contenido"] = image

    let jsonData = try! JSONSerialization.data(withJSONObject: data, options: JSONSerialization.WritingOptions(rawValue: 0))
    let request = NSMutableURLRequest(url: NSURL(string:"http://192.168.2.101:3001/api/imagen") as! URL)
    request.httpMethod = "POST"
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    request.addValue("application/json", forHTTPHeaderField: "Accept")
    request.httpBody = jsonData

    URLSession.shared.dataTask(with: request as URLRequest, completionHandler: self.responseImage).resume()
}
// Función de control de la respuesta del servidor tras enviar una imagen
func responseImage(data: Data?, response: URLResponse?, error: Error?) {

    if (error != nil) {
        print("No se ha podido contactar con el servidor")
    }
    else{
        // Connected, check response, GET status codes.
        let statusCode = (response as! HTTPURLResponse).statusCode

        switch statusCode{
            case 200:
                print("Imagen subida")

            default:
                print("Error en la petición al servidor")
        }
    }
}

第一张图片上传正确(回复状态代码= 200),但下一张图片不是

这是我根据您的建议修改过的代码:

func sendImage(image:String, completion: @escaping () -> Void) {

    let data = NSMutableDictionary()

    let id:Int = (idea?.id)!
    let pasoAct = idea?.pasoActual
    data["id_idea"] = id
    data["id_paso"] = pasoAct
    data["contenido"] = image

    let jsonData = try! JSONSerialization.data(withJSONObject: data, options: JSONSerialization.WritingOptions(rawValue: 0))
    let request = NSMutableURLRequest(url: NSURL(string:"http://192.168.2.101:3001/api/imagen") as! URL)
    request.httpMethod = "POST"
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    request.addValue("application/json", forHTTPHeaderField: "Accept")
    request.httpBody = jsonData

    URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) in
        self.responseImage(data: data, response: response, error: error)

        // When responseImage is complete, call the completion handler
        completion()
    }
}


// And the following code is called when I try to send the array of images
let group = DispatchGroup()
    let asyncQueue = DispatchQueue(label: "asyncQueue", attributes: .concurrent)
    for image in self.arrayImages {

        asyncQueue.async {
            group.enter()

            let strBase64:String = image.base64EncodedString(options: .lineLength64Characters)
            self.sendImage(image: strBase64) {
                group.leave()
            }
        }
    }

    group.wait()

2 个答案:

答案 0 :(得分:1)

在您的情况下,最好使用DispatchQueue.concurrentPerform(iterations: self.arrayImages.count) { i in let strBase64 = self.arrayImages[i].base64EncodedString(options: .lineLength64Characters) self.sendImage(image: strBase64) } print("Done") // This line will only be executed after self.send() is // called on all images. However, this does not mean that // the server has received all the images.

std::vector

答案 1 :(得分:1)

您可以使用DispatchGroup ...

let group = DispatchGroup()

for image in self.arrayImages {

    let workItem = DispatchWorkItem(qos: .default, flags: []) {
        let strBase64:String = image.base64EncodedString(options: .lineLength64Characters)
        self.sendImage(image: strBase64)
    }
    // perform the task asynchronously
    group.notify(queue: asyncQueue, work: workItem)
}

group.wait()

// Done!!

修改 现在您已经更新了问题,我可以看到您正在进行另一次异步通话。您可以按如下方式处理:

func sendImage(image:String, completion: @escaping () -> Void) {

        // Your code here

        URLSession.shared.dataTask(with: URL()) { (data, response, error) in
            self.responseImage(data: data, response: response, error: error)

            // When responseImage is complete, call the completion handler
            completion()
         }

}

let group = DispatchGroup()

for image in self.arrayImages {

    asyncQueue.async {
        group.enter()

        let strBase64:String = image.base64EncodedString(options: .lineLength64Characters)
        self.sendImage(image: strBase64) {
            group.leave()
        }
    }
}

group.wait()

// Done!!

我想遵循的一条简单规则是始终将完成处理程序作为参数添加到我写的每个异步函数中。