2013-07-20 27 views
0

對不起,這有點羅嗦,但我想確保我清楚! ;-)NSOperationQueue的線程只是不死

我有一個使用FFMPEG流媒體RTSP的iOS應用程序。我使用NSOperationQueue進行了多線程FFMPEG,因此除了將圖像繪製到屏幕上之外,大多數工作都發生在後臺線程中。 太棒了! ......除了NSOperationQueue創建的線程永遠不會死!

我初始化隊列在類init方法用:

self->opQ = [[NSOperationQueue alloc] init]; 
[self->opQ setMaxConcurrentOperationCount:1]; 

我方法添加到隊列使用塊:

[self->opQ addOperationWithBlock:^{ 
     [self haveConnectedSuccessfullyOperation]; 
}]; 

或者

[self->opQ addOperationWithBlock:^{ 
     if (SOME_CONDITION) { 
      [self performSelectorOnMainThread:@selector(DO_SOME_CRAP) withObject:nil waitUntilDone:NO]; 
     } 
    }]; 

後來時,我需要拆除RTSP流,除了告訴FFMPEG關閉,我打電話:

[self->opQ cancelAllOperations]; 

這確實阻止了線程從事任何工作,但從未真正銷燬它們。在下面,你會看到一個線程的屏幕截圖,它什麼都不做。這是我的線程多次啓動/停止FFMPEG後的樣子。

Bad threads

我似乎記得閱讀蘋果文檔在NSOperations和它們在一旦被執行完,除非另有引用被破壞運行的線程。這似乎並非如此。

難道我只需要摧毀NSOperationQueue,然後重新初始化它,當我需要啓動FFMPEG再次(我才意識到我沒有嘗試這樣做)?任何人都知道我需要如何殺死這些額外的線程?

謝謝!

+2

爲什麼你在使用' - >'?請不要。 –

+0

當您遇到此問題時,是否有任何操作實際留在隊列中? –

+0

@jacob爲什麼不使用 - >?我已閱讀了多個文字,提示其用法。 還有其他的操作正在運行,因爲一個循環不斷地向隊列提供流媒體和播放視頻源的其他操作。 – u2Fan

回答

1

我通過創建NSBlockOperation:這樣我就可以監視isCancelled狀態,同時也使新NSBlockOperation s'的內容更聰明,這樣我簡化,將添加操作隊列中的常規解決它。

...另外,我做了一個NSOperationQueue n00b錯誤:我正在循環基礎上添加操作到隊列,每秒激發30次(匹配視頻的幀速率)。然而,現在的操作被添加到隊列中只有一次,在循環行爲中包含,而不是具有循環操作添加到隊列中的操作。

以前,我有這樣的事情(僞代碼,因爲我沒有跟我的項目):

NSTimer *frameRateTimeout = [NSTimer scheduledTimerWithTimeInterval:1/DESIRED_FRAMES_PER_SECOND target:self selector:@selector(ADD_OPERATION_TO_QUEUE_METHOD:) userInfo:nil repeats:YES]; 

-(void)ADD_OPERATION_TO_QUEUE_METHOD:(NSTimer *)timer { 
    [opQ addOperation:displayFrame]; 
} 

哪個效果很好,因爲操作系統將正確地管理隊列,但它是效率不高,並保持這些線程永存。

現在,它更像是:

-(id)init { 
    self = [super init]; 
    if (self) { 
     // alloc/init operation queue 
     ... 
     // alloc/init 'displayFrame' 
     displayFrame = [NSBlockOperation blockOperationWithBlock:^{ 
     while (SOME_CONDITION && ![displayFrame isCancelled]) { 
      if (playVideo) { 
       // DO STUFF 
       [NSThread sleepForTimeInterval:FRAME_RATE]; 
      } 
      else { // teardown stream 
       // DO STUFF 
       break; 
      } 
     } 
     }]; 
    } 

    return self; 
} 

- (void)Some_method_called_after_getting_video_ready_to_play { 
    [opQ addOperation:displayFrame]; 
} 

謝謝,雅各布Relkin,爲應對我的職務。
如果有人需要進一步澄清,讓我知道,一旦我的項目再次在我手中,我會發布更好的代碼。