2

我在 a 中运行一个数学公式NSOperation

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue setMaxConcurrentOperationCount:20];

for (int i = 0; i<runCount; i++) {
    NSInvocationOperation *op =[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(runFormula:) object:frm];
    [queue addOperation:op];
}

这是方法体:

-(void)runFormula:(NSDictionary *)frm
{
    NSMutableString *formula = [[frm objectForKey:kFormulaExpresion] mutableCopy];
    NSArray *variables = [frm objectForKey:kVariableArray];
    evals = [self evaluateVariables:variables];

    for (NSDictionary *var in evals) {
        NSString *sym = [var objectForKey:kVariableSymbol];
        [formula replaceOccurrencesOfString:sym withString:[[var objectForKey:@"numVal"] stringValue] options:NSCaseInsensitiveSearch range:NSMakeRange(0, [formula length])];
    }

    //parse formula

    double result = [formula evaluateMath];
    NSLog(@"formula %@ the result : %f",formula,result);
    NSNumber *resNo = [NSNumber numberWithDouble:result];
    [self performSelectorOnMainThread:@selector(addNewResult:) withObject:resNo waitUntilDone:NO];
}

问题是,如果我将 runCount 设为 100,我只会收到大约 96 个结果……这是为什么呢?还有一件事:第一个结果是胡说八道,但其他94-95都可以。

这是数据聚合方法...

#pragma mark -- data aggregation delegate
-(void)addNewResult:(NSNumber *)nr
{
     NSLog(@"index : %i result: %f",currentIndex,[nr doubleValue]);
    [[self delegate] didReceiveResult:nr];
    resultsArray[currentIndex]=[nr doubleValue];
    currentIndex ++;
    if (  (currentIndex % percentVal) == 0) {
        [[self delegate] percentCompleted];
    }
}

问题可能是这与并发方法在同一个类中吗?

4

1 回答 1

0

两个想法:

  1. 您没有向我们展示足够多的东西来诊断这一点,但是您可能有 20 个并发操作迭代您的evals实例变量,它们都会更新。那可不好。[self evaluateVariables:variables]我可能会为您可以迭代的结果建议一个局部变量。请参阅下面的示例。

  2. 当您说只有 96 正在运行时,您绝对确定吗?他们是否有可能没有按照您将它们添加到队列中的顺序完成?

所以,我可能会建议:

-(void)runFormula:(NSDictionary *)frm
{
    NSMutableString *formula = [[frm objectForKey:kFormulaExpresion] mutableCopy];
    NSArray *variables = [frm objectForKey:kVariableArray];
    NSArray *evals = [self evaluateVariables:variables];  // LOCAL VAR

    for (NSDictionary *var in evals) {
        NSString *sym = [var objectForKey:kVariableSymbol];
        [formula replaceOccurrencesOfString:sym withString:[[var objectForKey:@"numVal"] stringValue] options:NSCaseInsensitiveSearch range:NSMakeRange(0, [formula length])];
    }

    //parse formula

    double result = [formula evaluateMath];
    NSLog(@"formula %@ the result : %f",formula,result);
    NSNumber *resNo = [NSNumber numberWithDouble:result];
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        [self addNewResult:resNo];
    }];
}

请注意,在上面的代码块中,就风格而言,如果我使用操作,则NSOperationQueue在调度回主队列时我会停留在隐喻中。没关系,我不认为,但感觉更一致。

同样,在初始调用中,您始终可以考虑块变体,如果它使其更具可读性。如果您想查看识别各个操作的诊断信息,还可以记录日志i,这样您就可以确保它们都在运行:

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue setMaxConcurrentOperationCount:20];

for (int i = 0; i < runCount; i++) {
    [queue addOperationWithBlock:^{
        NSLog("started %d", i);        // log i if you want to see that diagnostic information, too
        [self runFormula:frm];
        NSLog("finished %d", i);
    }];
}
于 2013-01-28T20:51:46.980 回答