8

我在这里有点困惑,我使用队列,我到了一个我有点迷失的地步。

我有一个名为getPeoplewho has to fetch 来自服务器的用户图片的方法。为了不阻止我使用的应用程序:

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

每次用户点击按钮时都会执行前面的代码。诸如“给我这张专辑中的照片”之类的内容,然后再次点击“现在我想要其他专辑中的人们的照片”,不同的照片和不同数量的照片。如果用户非常快地点击按钮,当第二个队列已经开始时,第一个队列不会完成获取数据。我将数据存储在getPeopleNSMutableArray 中,因此当 2 个队列同时执行时,它们都在同一个数组上写入,并且应用程序由于超出范围异常而崩溃。通过数据的方式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++;
    }
}

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

4

3 回答 3

12

如果可能,我建议您避免与信号量同步。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>];
         });
    }
}

如果您想替换数组,而不是让两个线程以交错方式添加到它,您可以在后台累积整个数组并将整个数组调度peopleInArray到主队列。

如果你想取消,你可以用一个标志自己实现它,或者你应该考虑使用NSOperationandNSOperationQueue而不是 GCD。这些具有内置的取消概念,尽管您的自定义操作仍需要检查它们是否已被取消并停止工作。

于 2012-04-11T17:17:20.097 回答
2

你是对的,没有办法停止已调度的队列。getPeople您可以做的一件事是使用信号量来确保同时只有一个队列正在访问(这可能更有趣)。

如果您只是想避免用户多次单击按钮,您可以使用在异步调度stillExecuting中设置为的 bool 变量,并在. 在创建之前,您只需检查是否仍在执行。YESNOgetPeoplegetPeopleQueuegetPeople

if(!stillExecuting) {
       dispatch_queue_t getPeopleQueue = dispatch_queue_create("Pinta Ocupantes", NULL);
        dispatch_async(getPeopleQueue, ^{
           [self getPeople];
        });
       dispatch_release(getPeopleQueue);
}
于 2012-04-11T16:06:43.053 回答
-1

NSString *lastLoginTime =@"您上次登录时间";

    NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
    [dateFormat setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    NSDate* date1 = [dateFormat lastLoginTime];
    NSDate* date2 = [dateFormat dateFromString:[NSString currentDateTime]];
    NSTimeInterval secondsSinceLastLogin = [date2 timeIntervalSinceDate:date1];
    //  NSLog(@"Seconds Since Last Login: %g", secondsSinceLastLogin);
    int hours = (int)secondsSinceLastLogin / 3600;
于 2015-05-18T08:29:36.643 回答