调度队列如何工作

sub*_*arb 5 objective-c grand-central-dispatch

我在这里有点困惑,我使用队列,我到了一点,我有点迷失.

我有一个名为getPeoplewho 的方法,必须从服务器获取用户的图片.为了不阻止应用程序,我使用了这个:

 -(IBAction)seeMorePeople{
        dispatch_queue_t getPeopleQueue = dispatch_queue_create("Pinta Ocupantes", NULL);
        dispatch_async(getPeopleQueue, ^{
           [self getPeople];
        });
       dispatch_release(getPeopleQueue);
 }
Run Code Online (Sandbox Code Playgroud)

每次用户点击按钮时都会执行上一个代码.像"从这张专辑给我照片"然后另一个点击"现在我想要来自其他专辑的人物照片",不同的照片和不同数量的照片.如果用户非常快地点击按钮,则第一个队列在第二个队列已经启动时不会完成获取数据.在getPeople我将数据存储在NSMutableArray中时,所以当两个队列同时执行时,两个队列都在同一个数组上写入,并且应用程序因超出范围异常而崩溃.getPeople通过数据的方式是这样的:

-(void)getPeople:(NSDictionary *)peopleDictionary{
    //I receive an NSDictionary and I go through it
    NSArray *keys = [peopleDictionary allKeys];
    int indexOfArray = 0;
    for(NSString *key in keys){
         //Complex operation that are not important
         [peopleInArray insertObjetAtIndex:indexOfArray];//People in array is a global variable
         indexOfArray++;
    }
}
Run Code Online (Sandbox Code Playgroud)

我无法弄清楚的是如何摆脱这种情况,我想在第二个队列进入时停止第一个队列,但是GCD没有这个选项...任何其他方式来完成这个,希望没有专业重新编码,无论如何我现在没有想法,所以任何线索都会有所帮助.

Ken*_*ses 8

如果可能的话,我建议您避免与信号量同步.GCD的设计是为了避免这种情况.后台任务应该准备数据但不要触摸外部状态.在准备数据时,它应该将外部状态的更新分派给串行队列,或者如果状态绑定到GUI,则分配给主队列.

所以,像这样:

-(void)getPeople:(NSDictionary *)peopleDictionary{
    //I receive an NSDictionary and I go through it
    NSArray *keys = [peopleDictionary allKeys];
    for(NSString *key in keys){
         //Complex operation that are not important
         dispatch_async(dispatch_get_main_queue(), ^{
             [peopleInArray addObject:<whatever>];
         });
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您想要替换数组,而不是以交错方式添加两个线程,则可以在后台累积整个数组,并将整个数据集设置peopleInArray到主队列中.

如果你想要取消,你可以用旗子自己实现,或者你应该考虑使用NSOperationNSOperationQueue不是GCD.虽然您的自定义操作仍然需要检查它们是否已被取消并停止工作,但它们具有内置取消的概念.