2017-03-08 81 views
2

我试图发送我的API迭代图像数组的多张照片。 我想发送不同的线程中的每个图像,但是当第一个线程 完成它不等待其余的线程和发送只有一个图片 。Swift 3:执行多个线程并等待敲定

这是我的代码:

// 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) 
     } 

    } 

我最近在斯威夫特开始编程,我不知道如何同步线程。请问你能帮帮我吗?

代码来执行我的要求是:

// 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() 

回答

1

在你的情况下,可以更好地使用concurrentPerform

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. 
+0

同意。以防所有的异步基本上执行相同的代码,我也建议这个 –

+0

不适合我:( –

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!! 

一个简单的规则我喜欢追随,是总是作为参数添加完成处理程序,以我写的每一个异步FUNC。

+0

而在这种情况下id使用'DispatchQueue.concurrentPerform'这个答案有价值在显示一般的做法 –

+0

didn' t为我工作第一张图片上传然后我的API响应失败 –

+0

我发送我的图像作为一个64Bytes字符串到我的API,我需要为每个请求启动一个线程,因为我的API也抛出一个“请求实体大“的错误 –