2012-07-07 5 views
3

많은 문자열 (문자열)을 만들고로드하고 있습니다. 애니메이션이 원활하게 실행되도록하기 위해 작업을 별도의 작업자 스레드로 오프로드합니다. 그것은 내가 원하는 방식으로 다소 정확하게 작동하는 것으로 보이지만 오래된 장치 (iPhone 3GS)에서는 때로는 긴 (1 초) 지연을 느낍니다. 때때로 발생합니다. 이제 내가 제대로하고 있는지 또는 개념적으로 문제가 있는지 궁금합니다. 아래에 소스 코드를 붙여 넣습니다.비동기 텍스처로드 iPhone OpenGL ES 2

또한 GLKit TextureLoader를 사용하고 싶지 않습니다. 왜냐하면로드하는 부분뿐만 아니라 다른 스레드에 텍스처 생성 작업을 오프로드하기를 원하기 때문입니다. http://youtu.be/U03p4ZhLjvY?hd=1

NSLock*      _textureLock; 
NSMutableDictionary*  _texturesWithString; 
NSMutableArray*    _texturesWithStringLoading; 

// This is called when I request a new texture from the drawing routine. 
// If this function returns 0, it means the texture is not ready and Im not displaying it. 

-(unsigned int)getTextureWithString:(NSString*)string { 
    Texture2D* _texture = [_texturesWithString objectForKey:string]; 
    if (_texture==nil){ 
     if (![_texturesWithStringLoading containsObject:string]){ 
      [_texturesWithStringLoading addObject:string]; 
      NSDictionary* dic = [[NSDictionary alloc] initWithObjectsAndKeys:string,@"string", nil]; 
      NSThread* thread = [[NSThread alloc] initWithTarget:self selector:@selector(loadTextureWithDictionary:)object:dic]; 
      thread.threadPriority = 0.01; 
      [thread start]; 
      [thread release]; 
     } 
     return 0; 
    } 
    return _texture.name; 
} 

// This is executed on a separate worker thread. 
// The lock makes sure that there are not hundreds of separate threads all creating a texture at the same time and therefore slowing everything down. 
// There must be a smarter way of doing that. Please let me know if you know how! ;-) 
-(void)loadTextureWithOptions:(NSDictionary*)_dic{ 
    [_textureLock lock]; 
    EAGLContext* context = [[SharegroupManager defaultSharegroup] getNewContext]; 
    [EAGLContext setCurrentContext: context]; 

    NSString* string = [_dic objectForKey:@"string"]; 
    Texture2D* _texture = [[Texture2D alloc] initWithStringModified:string]; 

    if (_texture!=nil) { 
     NSDictionary* _newdic = [[NSDictionary alloc] initWithObjectsAndKeys:_texture,@"texture",string,@"string", nil]; 
     [self performSelectorOnMainThread:@selector(doneLoadingTexture:) withObject:_newdic waitUntilDone:NO]; 
     [_newdic release]; 
     [_texture release]; 
    } 
    [EAGLContext setCurrentContext: nil]; 
    [context release]; 
    [_textureLock unlock]; 
} 

// This callback is executed on the main thread and marks adds the texture to the texture cache. 
-(void)doneLoadingTextureWithDictionary:(NSDictionary*)_dic{ 
    [_texturesWithString setValue:[_dic objectForKey:@"texture"] forKey:[_dic objectForKey:@"string"]]; 
    [_texturesWithStringLoading removeObject:[_dic objectForKey:@"string"]]; 
} 
+0

질문을 게시 한 직후와 마찬가지로 정상적으로 작동합니다. 이제는 너무 많은 NSThread를 생성하지 않고 NSOperationQueue를 사용합니다. 그게 문제를 해결할 것 같다 'maxConcurrentOperationCount'를 설정할 수 있습니다. 나는 내가 너에게 어리석은 다른 것을하고 있는지 아직도 듣고 싶다. – hanno

+1

리소스 제한 문제가있는 경우 디스패치 세마포를 살펴보십시오. http://www.mikeash.com/pyblog/friday-qa-2009-09-25-gcd-practicum.html. 나는 I/O 속도가 처리 속도보다 더 제한적일 수있는 이와 같은 항목에 일반적으로이를 사용합니다. –

+0

감사합니다. 다른 것 : 공유 그룹에서 새 컨텍스트를 가져오고 설정하는 데는 도구에 따라 많은 시간이 필요합니다. 추가 컨텍스트 중 하나를 작성하고 스레드간에 재사용해야합니까? 한 번에 하나의 스레드에서만 액세스 할 수 있도록해야합니까? 나는 어딘가에서 내가 그렇게해서는 안되는 것을 기억하는 이유를 기억하지 못한다. – hanno

답변

0

문제는 너무 많은 스레드가 동시에 시작된 것이 었습니다 :

경우

당신은 내가 이러한 텍스처를 필요 궁금는이 비디오를 보라. 이제 NSThreads 대신 NSOperationQueue을 사용하고 있습니다. 그래서 maxConcurrentOperationCount을 설정하고 텍스처 로딩을 수행하는 추가 백그라운드 스레드를 하나만 실행할 수 있습니다.