2016-09-01 85 views
3

我有以下代码:如何等待所有NSOperations完成?

func testFunc(completion: (Bool) -> Void) { 
    let queue = NSOperationQueue() 
    queue.maxConcurrentOperationCount = 1 

    for i in 1...3 { 
     queue.addOperationWithBlock{ 
      Alamofire.request(.GET, "https://httpbin.org/get").responseJSON { response in 
       switch (response.result){ 
       case .Failure: 
        print("error") 
        break; 
       case .Success: 
        print("i = \(i)") 
       } 
      } 
     } 
     //queue.addOperationAfterLast(operation) 
    } 
    queue.waitUntilAllOperationsAreFinished() 
    print("finished") 
} 

和输出是:

finished 
i = 3 
i = 1 
i = 2 

但我希望以下内容:

i = 3 
i = 1 
i = 2 
finished 

那么,为什么queue.waitUntilAllOperationsAreFinished()不等待?

回答

5

您添加到队列中的每个操作都会立即执行,因为Alamofire.request只是在不等待响应数据的情况下返回。

此外,那里有可能发生死锁。由于responseJSON块默认在主队列中执行,因此通过调用waitUntilAllOperationsAreFinished来阻塞主线程将阻止它完全执行完成块。

首先,为了解决死锁问题,您可以告诉Alamofire在不同的队列中执行完成块,其次,您可以使用dispatch_group_t来分组异步HTTP请求的数量并保持主线程等待所有组中的那些请求完成执行:

let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0) 
let group = dispatch_group_create() 
for i in 1...3 { 
    dispatch_group_enter(group) 
    Alamofire.request(.GET, "https://httpbin.org/get").responseJSON(queue: queue, options: .AllowFragments) { response in 
    print(i) 
    dispatch_async(dispatch_get_main_queue()) { 
     // Main thread is still blocked. You can update the UI here but it will take effect after all HTTP requests are finished. 
    } 
    dispatch_group_leave(group) 
    } 
} 
dispatch_group_wait(group, DISPATCH_TIME_FOREVER) 
print("finished") 
2

我建议你使用KVO,并观察队列何时完成所有任务,而不是阻塞当前线程,直到所有操作完成。或者你可以使用依赖关系。看看this SO问题