2013-05-12 28 views
8

Điều này có vẻ như nó thực sự đơn giản nhưng tôi gặp rất nhiều rắc rối. Tôi có một chức năng kích hoạt một loạt các chức năng khác chạy trong nền và có các khối hoàn thành. Tôi muốn chức năng của tôi đợi cho đến khi tất cả các khối hoàn thành được gọi trước khi nó trả về.iOS: Không trở về từ chức năng cho đến khi nhiều chủ đề nền hoàn thành

Tôi không có quyền kiểm soát chức năng tôi đang gọi thực hiện trong nền. Nếu không, tôi sẽ sửa đổi nó để sử dụng dispatch_async với hàng đợi của riêng tôi và sau đó chờ đợi trên hàng đợi đó để kết thúc.

Ví dụ về những gì hoàn cảnh của tôi trông giống như:

- (void)functionThatShouldBeSynchronous { 
    for (int i = 0; i < 10; i++) { 
     [self doSomethingInBackground:^{ 
      NSLog(@"completed!"); 
     }]; 
    } 
    // How do I wait until all 10 threads have completed before returning? 
} 

- (void)doSomethingInBackground:(void(^)())completion { 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ 
     [NSThread sleepForTimeInterval:1.0f]; // Do stuff 
     completion(); // Execute completion block 
    }); 
} 

Cảm ơn trước.

+1

Bất kể bạn kết thúc làm gì, ** cũng không chặn luồng chính **. – bbum

+0

@bbum chỉ vì tò mò, hậu quả tiềm ẩn của việc này là gì? –

+0

Tốt nhất? Khả năng phản hồi kém và hoạt ảnh không tốt. Lúc tồi tệ nhất? Nếu bạn chặn luồng chính đủ lâu, hệ thống sẽ giết ứng dụng của bạn với giả định rằng nó bị khóa. – bbum

Trả lời

28

Sử dụng một nhóm công văn như thế này:

- (void)functionThatShouldBeSynchronous { 
    dispatch_group_t taskGroup = dispatch_group_create(); 

    for (int i = 0; i < 10; i++) { 
     dispatch_group_enter(taskGroup); 
     [self doSomethingInBackground:^{ 
      NSLog(@"completed!"); 
      dispatch_group_leave(taskGroup); 
     }]; 
    } 

    // Waiting for threads 
    dispatch_group_wait(taskGroup, DISPATCH_TIME_FOREVER); 
    dispatch_release(taskGroup); 

    // Background work complete 
} 

Nếu bạn muốn có một thời gian chờ đợi cho các chủ đề bạn có thể thay đổi dòng dispatch_group_wait này

// Waiting 10 seconds before giving up 
if (dispatch_group_wait(taskGroup, dispatch_time(DISPATCH_TIME_NOW, 10000000000)) != 0) { 
    // Timeout 
} 

Các tham số là trong nano giây.

Khi bbum đang nói, bạn không nên chặn chuỗi chính. Trong trường hợp đó, bạn có thể làm như sau:

typedef void(^MyCompletionHandler)(); 
-(void)functionDoingBackgroundWorkWithCompletionHandler:(MyCompletionHandler)completionHandler { 
    dispatch_group_t taskGroup = dispatch_group_create(); 

    for (int i = 0; i < 10; i++) { 
     dispatch_group_enter(taskGroup); 
     [self doSomethingInBackground:^{ 
      NSLog(@"completed!"); 
      dispatch_group_leave(taskGroup); 
     }]; 
    } 

    dispatch_queue_t waitingQueue = dispatch_queue_create("com.mycompany.myapp.waitingQueue", DISPATCH_QUEUE_CONCURRENT); 
    dispatch_async(waitingQueue, ^{ 
     // Waiting for threads 
     dispatch_group_wait(taskGroup, DISPATCH_TIME_FOREVER); 
     dispatch_release(taskGroup); 


     // Background work complete 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      // Calling the completion handler on the main thread (If you like) 
      completionHandler(); 
     }); 
     dispatch_release(waitingQueue); 
    }); 
} 
+0

Hoạt động tuyệt vời. Cảm ơn! –

Các vấn đề liên quan