выполнение останавливается на [textView insertText:] без исключения! - PullRequest
0 голосов
/ 16 ноября 2010

Я пишу очень простое приложение для OSX. В этом приложении есть основной поток, который постоянно обновляет некоторые данные, затем вычисляет некоторые статистические данные и печатает их в textView.

Во время разработки я использовал тот же полученный IBAction, чтобы выполнить этот цикл. Я все заработал, затем переключился на NSThread, чтобы предотвратить блокировку интерфейса во время вычислений.

Как только я это сделал, приложение начало работать очень мало циклов (около 7-8), затем все приложение зависает без каких-либо исключений. Отладкой я заметил, что он зависает при попытке напечатать статистику в textView, и я абсолютно не знаю, как решить эту проблему. Это работает, если не внутри потока ... Кто-нибудь может помочь? Код ниже. Заранее спасибо:)

-(IBAction) Evolve:(id)sender{
 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 [NSThread detachNewThreadSelector:@selector(Evolve) toTarget:self withObject:nil];
 [pool drain];
}

И это весь цикл

-(void) Evolve{

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    srandom(time(NULL));

    //Tag 0: Minimo, Tag 1: Massimo
    int tagMinMax = [MinMax selectedTag];

    //Tag 0: Rimpiazza sempre, Tag 1: Rimpiazza solo se migliori
    int tagRimpiazzo = [[Rimpiazzo selectedItem] tag];

    int PopNum = [tf_popNum intValue];
    int maxGen = [tf_maxGen intValue];
    int target = [tf_targetVal intValue];
    int chromosomeLength = [tf_chromosomeLength intValue];

    Environment *env = [[Environment alloc] init];

    NSMutableArray *pop = [[NSMutableArray alloc] init];
    for (int i = 0; i < PopNum; i++) {
        [pop addObject:[[Individual alloc] initWithRandomGenesWithChromosomeLength:chromosomeLength]];
    }

    [env setPopulation:pop];
    [pop release];

    BOOL earlyBestFound = NO;
    Individual *earlyBest = nil;
    int i=0;
    float best, avg;
    while (i<maxGen && !earlyBestFound) {
        NSLog(@"while");
        NSArray *parents = [env selectParents];
        NSLog(@"parents selected");
        NSMutableArray *offspring = [[NSMutableArray alloc] init];
        for (int i = 0; i < [parents count]; i+=2) {
            if (i+1<[parents count]) {
                NSLog(@"beginning SEX");
                Individual *parent1 = [parents objectAtIndex:i];
                Individual *parent2 = [parents objectAtIndex:i+1];

                NSArray *children = [parent1 kCrossOverWithOtherIndividual:1 individual:parent2];

                Individual *child1 = [children objectAtIndex:0];
                Individual *child2 = [children objectAtIndex:1];

                NSLog(@"children born");

                if (tagRimpiazzo!=0) {
                    if (([child1 fitness] > [parent1 fitness] && tagMinMax == 0)||([child1 fitness] < [parent1 fitness] && tagMinMax == 1)) {
                        child1 = parent1;
                    }
                    if (([child2 fitness] > [parent2 fitness] && tagMinMax == 0)||([child2 fitness] < [parent2 fitness] && tagMinMax == 1)) {
                        child2 = parent2;
                    }
                }

                NSLog(@"Replacement happened");

                [offspring addObject:child1];
                [offspring addObject:child2];
            }
        }
        NSLog(@"Calculating statistics");
        avg = 0;
        for(Individual *X in offspring){

            if (([X fitness] > best && tagMinMax == 1)||([X fitness] < best && tagMinMax == 0)) {
                best = [X fitness];
            }

            avg += [X fitness];

            if ([X fitness]==target) {
                earlyBestFound = YES;
                earlyBest = X;
            }
        }
        avg = avg/(float)PopNum;

        [env setPopulation:offspring];

        NSLog(@"Releasing some memory");

        [offspring release];

        NSLog(@"Printing statistics");
        NSString *toPrint = [NSString stringWithFormat:@"Fine generazione: %d avg: %.2f best: %.2f \r\n", i,avg,best];
        [textView insertText:toPrint];

        i++;
    }

    NSLog(@"Fine");

    NSString *toPrint = [NSString stringWithFormat:@"Fine! best: %.2f - avg: %.2f \r\n", i,avg,best];
    [textView insertText:toPrint];

    [env release];

    [pool drain];
}

P.S. Извините, если английский не идеален, я итальянец :)

1 Ответ

2 голосов
/ 16 ноября 2010

Ваше приложение падает, потому что вы обращаетесь к textView из фонового потока. Доступ к объектам пользовательского интерфейса возможен только из основного потока.

Чтобы решить эту проблему, вам необходимо отправить обновления текстового обзора в основной поток пользовательского интерфейса. Вы можете сделать это, используя метод -performSelectorOnMainThread:. Например:

[textView performSelectorOnMainThread:@selector(insertText:) 
                           withObject:toPrint 
                        waitUntilDone:YES];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...