2011-09-26 6 views
1

무한 루프를 실행하는 간단한 스레드가 있습니다. 결국 루프는 초당 수천 번 USB 포트에서 직렬 데이터를 확인하지만 현재는 매 초마다 NSTextView의 사용자 지정 클래스에 무언가를 씁니다.GUI를 사용한 NSThread 타이밍 문제

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); 
} 

문제는 실제로 산발적으로 기록된다는 것입니다. 그것은 하나 또는 둘을 할 것이고, 10 초를 기다렸다가 한 번에 열을 뱉어 낼 것입니다. 작문 줄을 NSLog(@"test")으로 바꾸면 좋은 간격으로 기록됩니다. 텍스트 필드에 입력을 받아 들여 텍스트보기에 넣는 주 스레드에 또 다른 테스트 메서드가 있는데, 이렇게하면 자식 스레드의 가장 최근 쓰기를 포함하도록 텍스트보기가 업데이트됩니다. 어쨌든이 시점에서 아무 것도 방해해서는 안됩니다.하지만 확실한 모든 것을 모든 곳에 고정 시켰습니다. 미리 감사드립니다.

+1

잠금 개체 란 무엇입니까? [잠금 잠금]과 [잠금 해제]는 무엇을합니까? – Davyd

+0

잠금 개체는 NSLock의 인스턴스입니다. 서로 다른 두 위치에서 코드를 잠그면 동시에 발생하지 않습니다. 위의 예제에서는 불필요하지만 일반적으로 스레드가 다른 스레드가 사용하는 변수를 수정하거나 읽는 중일 때 사용해야합니다. – Andrew

답변

3

UI에 영향을주는 작업은 항상 주 스레드에서 수행해야합니다. 자식 스레드가 결과를 보유하는 임시 개체를 만든 다음 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]; // ? 

} 
+0

이것은 매력처럼 작동했습니다! 감사! – Andrew

1

저는 백그라운드 스레드의 NSTextStorage에서 어떤 것도 호출하는 것을 조심해야합니다. NSTextView는 NSTextStorage 변경 사항에 반응하며, 주 스레드가 아닌 모든 UI 코드는 예측할 수없는 문제가 발생할 것이라고 생각합니다.

주 스레드에 새 문자열을 보내고 -replaceCharactersInRange:을 호출하면됩니다.