2017-03-08 37 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也拋出一個「請求實體大「的錯誤 –