7

Hai tác vụ nền đồng thời cần vá hai mảng riêng biệt cần được hợp nhất trong khối dispatch_group_notify. Vấn đề là khối đầu tiên bị vượt quá nhưng dispatch_group_notify bị vượt quá mà không chờ đợi thực thi của tác vụ nền thứ hai. Sự khác biệt duy nhất giữa chúng là người đầu tiên thực hiện tìm kiếm địa phương và người thứ hai thực hiện cuộc gọi từ xa đến một dịch vụ web.Bất cứ lý do nào khiến người thứ hai nhảy qua?dispatch_group_notify không chờ đợi cho một dispatch_group_async

Chỉnh sửa: Tôi cũng đã thử cách tiếp cận được đề cập trong https://stackoverflow.com/a/19580584/859742 bằng dispatch_barrier_async nhưng vẫn giống nhau.

dispatch_group_t taskGroup = dispatch_group_create(); 
dispatch_queue_t mainQueue = dispatch_get_main_queue(); 

__block NSArray *localAddresses; 
__block NSArray *remoteAddresses; 

//Get local array in the background 
dispatch_group_async(taskGroup, mainQueue, ^{ 
    //localAddresses is set 
}); 

//get remote array from server 
dispatch_group_async(taskGroup, mainQueue, ^{ 
[[MDAddressManager instance] searchForPlacesContainingText:query 
                 location:alocation 
                completion:^(NSArray* addresses, MDError *error){ 
     //remoteAddresses is set 
}); 


//Merge two arrays 
dispatch_group_notify(taskGroup, mainQueue, ^{ 
    //remoteAddresses and local addresses are merged 
}); 

Và phương pháp tìm kiếm từ xa trông như thế này

- (void)searchForPlacesContainingText:(NSString *)searchText 
         location:(CLLocation *)alocation 
         completion:(MDAddressManagerBlock)completionBlock 
{ 
NSDictionary *parameters = [[NSMutableDictionary alloc] init]; 

[parameters setValue:searchText forKey:@"input"]; 

[[MDHTTPClient sharedHTTPClient] getPath:@"v1/remotePlaces.json" 
           parameters:parameters 
           success:^(AFHTTPRequestOperation *operation, id dict) { 

    if ([MDHTTPClient isResponseValid:dict]) 
    { 
      completionBlock(returnArray, nil); 
    } 
    else 
    { 
      completionBlock(nil, nil); 
    } 

} failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
    EDLog(@"%@", error); 
    completionBlock(nil, [MDError errorAFNetworking:error]); 
}]; 
} 

Trả lời

13

Điều này là do phương pháp getPath của bạn chạy không đồng bộ. Bạn cần nó để không rời khỏi nhóm cho đến khi khối hoàn thành đó chạy. Vì vậy, thay vì thực hiện dispatch_group_async, bạn nên theo cách thủ công dispatch_group_enterdispatch_group_leave.

Bạn có thể thay đổi mã của bạn từ:

dispatch_group_async(taskGroup, mainQueue, ^{ 
    [[MDAddressManager instance] searchForPlacesContainingText:query 
                 location:alocation 
                completion:^(NSArray* addresses, MDError *error){ 
     //remoteAddresses is set 
    }]; 
}); 

Để:

dispatch_group_enter(taskGroup); 

[[MDAddressManager instance] searchForPlacesContainingText:query 
                location:alocation 
               completion:^(NSArray* addresses, MDError *error){ 
    //remoteAddresses is set 
    dispatch_group_leave(taskGroup); 
}); 

Điều đó sẽ đảm bảo rằng bạn không rời khỏi nhóm cho đến khi khối hoàn thành được gọi.


Ngoài ra, bạn có thể thay đổi searchForPlacesContainingText sử dụng dispatch_group_t tham số:

- (void)searchForPlacesContainingText:(NSString *)searchText 
          location:(CLLocation *)alocation 
           group:(dispatch_group_t)group 
          completion:(MDAddressManagerBlock)completionBlock 
{ 
    dispatch_group_enter(group); 

    NSDictionary *parameters = [[NSMutableDictionary alloc] init]; 

    [parameters setValue:searchText forKey:@"input"]; 

    [[MDHTTPClient sharedHTTPClient] getPath:@"v1/remotePlaces.json" 
            parameters:parameters 
            success:^(AFHTTPRequestOperation *operation, id dict) { 

     if ([MDHTTPClient isResponseValid:dict]) 
     { 
       completionBlock(returnArray, nil); 
     } 
     else 
     { 
       completionBlock(nil, nil); 
     } 

     dispatch_group_leave(group); 

    } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
     EDLog(@"%@", error); 
     completionBlock(nil, [MDError errorAFNetworking:error]); 

     dispatch_group_leave(group); 
    }]; 

} 

và thay đổi gọi của bạn để nó không làm dispatch_group_async, mà đúng hơn là chỉ vượt qua taskGroup tham số:

[[MDAddressManager instance] searchForPlacesContainingText:query 
                location:alocation 
                group:taskGroup 
               completion:^(NSArray* addresses, MDError *error) { 
    //remoteAddresses is set 
}); 
+0

cảm ơn bạn rất nhiều vì đã trả lời và giải thích tuyệt vời với các câu trả lời thay thế =) –

+0

Tôi hav e đang tìm kiếm một thứ như thế này khá lâu. :) ngón tay cái lên. : D – riyaz

+0

Bạn vẫn sử dụng dispatch_group_notify ở đây để được thông báo về việc hoàn thành nhóm? –

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