dispatch_group的實際使用案例,監聽多工
在發起網路請求時,我們一般會用非同步請求,這裡我們以 AFNetWorking 為例:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:@"http://octree.me/" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"Success");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error);
}];
假如我們要執行多個非同步請求,一般可以這麼寫
NSArray *urlStrings = @[ @"http://octree.me", @"http://google.com", @"http://github.com" ];
for(NSString urlString in urlStrings) {
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:urlString parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"Success");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error);
}];
}
假如我們需要在三個請求都完成或者失敗後進行一些處理,但是 manager 發起的請求時非同步處理的,也就是說當 manager 呼叫 GET:parameters:success:failure 會立即返回,當請求成功或失敗後才會呼叫各自的 block ,我們如何才能監控併發的非同步事件呢?並且他們的完成順序以及完成時間都是不確定的。
當然,你可以用一組 bool 值或者其他的標識記錄每個任務的完成進度,但是這樣的程式碼不僅醜陋,而且失去了擴充套件性。
這時候我們就可以用到 dispatch_group 了
dispatch_group 在任務組內的任務都完成的時候通過同步或者非同步的方式通知你
dispatch_group 提供了兩種通知方式, dispatch_group_wait 和 dispatch_group_notify
dispatch_group_wait 會阻塞當前執行緒,知道任務都完成時才會繼續執行下面的程式碼
我們可以使用 dispatch_group_wait 這樣實現:
NSArray *urlStrings = @[ @"http://octree.me", @"http://google.com", @"http://github.com" ];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
dispatch_group_t requestGroup = dispatch_group_create();
for(NSString urlString in urlStrings) {
dispatch_group_enter(requestGroup);
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:urlString parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"Success");
dispatch_group_leave(requestGroup);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error);
dispatch_group_leave(requestGroup);
}];
}
dispatch_group_wait(requestGroup, DISPATCH_TIME_FOREVER);
dispatch_async(dispatch_get_main_queue(), ^{
//doSomething;
});
}];
因為 dispatch_group_wait 會阻塞當前執行緒,所以我們要把他放到後臺執行,避免阻塞主執行緒。通過 dispatch_group_enter 和 dispatch_group_leave 手動通知任務的開始以及結束。 dispatch_group_wait 會阻塞當前執行緒,知道所有任務完成或者超時才會繼續執行下面的程式碼。
前面我們說過, dispatch_group 提供了兩種通知方式,我們已經瞭解了 dispatch_group_wait ,另一種是 dispath_group_notify ,這種方式相對於前面的顯得更為靈活。
dispatch_group_notify 是通過非同步的方式通知,所以,不會阻塞執行緒。於是,我們就可以這樣寫:
NSArray *urlStrings = @[ @"http://octree.me", @"http://google.com", @"http://github.com" ];
dispatch_group_t requestGroup = dispatch_group_create();
for(NSString urlString in urlStrings) {
dispatch_group_enter(requestGroup);
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:urlString parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"Success");
dispatch_group_leave(requestGroup);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error);
dispatch_group_leave(requestGroup);
}];
}
dispatch_group_notify(requestGroup, dispatch_get_main_queue(), ^{
//doSomething
});