1. 程式人生 > >dispatch_group的實際使用案例,監聽多工

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