NSOperationQueue的线程不会死

时间:2013-07-20 01:39:21

标签: ios multithreading ffmpeg 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

我似乎记得在Apple的文档中读到NSOperations及其运行的线程一旦执行就会被销毁,除非另有引用。情况似乎并非如此。

我是否只需要销毁NSOperationQueue,然后在需要再次启动FFMPEG时重新启动它(我刚才意识到我没有尝试过这个)?任何人都知道我需要如何杀死这些额外的线程?

谢谢!

1 个答案:

答案 0 :(得分: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];
}

谢谢Jacob Relkin回复我的帖子 如果有人需要进一步澄清,请告诉我,一旦我再次掌握了项目,我会发布更好的代码。