NSThread Timing Проблема с графическим интерфейсом - PullRequest
1 голос
/ 26 сентября 2011

У меня есть простой поток, который запускает бесконечный цикл. В конце концов, цикл будет проверять последовательные данные на USB-порту несколько тысяч раз в секунду, но в данный момент он просто записывает что-то в пользовательский класс NSTextView раз в секунду.

int i;
for (i=1; i>0; i++)
{
    [lock lock];
    [[self textStorage] replaceCharactersInRange:NSMakeRange([[self textStorage] length], 0) withString:@"test\n"];
    [lock unlock];
    sleep(1);
}

Проблема в том, что он пишет действительно спорадически. Это сделает один или два, затем подождите десять секунд и выплюнет десять из них одновременно. Если я заменю строку записи на NSLog(@"test"), она будет записываться с хорошими четными интервалами. У меня есть другой метод тестирования в главном потоке, который принимает ввод в текстовое поле и помещает его в текстовое представление, и при этом кажется, что обновление текстового представления обновляет последние записи дочернего потока. В любом случае, в этот момент не должно быть ничего, что могло бы помешать этому, но я все заблокировал, чтобы быть уверенным. Заранее спасибо.

Ответы [ 2 ]

3 голосов
/ 26 сентября 2011

Вы всегда должны выполнять операции, которые влияют на пользовательский интерфейс из основного потока.Вы можете попросить дочерний поток создать временный объект, содержащий результаты, а затем использовать performSelectorOnMainThread:withObject:waitUntilDone: для вызова другого метода, который внесет необходимые изменения в основной поток.

NSString * const MDResultKey = @"MDResult";

- (void)someMethod {
    // 
    int i;
    for (i=1; i>0; i++) {
         // if necessary, create an object to hold results
         NSDictionary *results = [NSDictionary 
               dictionaryWithObjectsAndKeys:@"test", MDResultKey, nil];

         [self performSelectorOnMainThread:@selector(updateUIWithResults:) 
                  withObject:results waitUntilDone:NO];

         sleep(1);
    }
}


- (void)updateUIWithResults:(NSDictionary *)results {
    NSString *result = [results objectForKey:MDResultKey];
    [lock lock]; // ?
    [[self textStorage] replaceCharactersInRange:
           NSMakeRange([[self textStorage] length], 0) withString:result];
    [lock unlock]; // ?

}
1 голос
/ 26 сентября 2011

Лично я бы с осторожностью вызывал что-нибудь для NSTextStorage в фоновом потоке. Я думаю, что NSTextView реагирует на любые изменения NSTextStorage, и любой код пользовательского интерфейса в неосновном потоке будет иметь непредсказуемые проблемы.

Я бы просто отправил новую строку в главный поток и вызвал -replaceCharactersInRange: там.

...