iOS AVFoundation和多线程

Giz*_*odo 2 multithreading avfoundation grand-central-dispatch ios gpuimage

在Apple的AVFoundation演示的每个示例代码中,所有会话任务都有一个单独的队列.

dispatch_queue_t sessionQueue = dispatch_queue_create("session queue", DISPATCH_QUEUE_SERIAL);
Run Code Online (Sandbox Code Playgroud)

这也用于观察焦点变化,曝光变化,白平衡变化等:

- (void)viewWillAppear:(BOOL)animated
{
     [super viewWillAppear:animated];
     dispatch_async([self sessionQueue], ^{
          [self addObservers];
          [[self session] startRunning];
     });
}

- (void)viewDidDisappear:(BOOL)animated
{
     dispatch_async([self sessionQueue], ^{
          [[self session] stopRunning];
          [self removeObservers];
     });
     [super viewDidDisappear:animated];

}
Run Code Online (Sandbox Code Playgroud)

当我遵循这个时,一切都很顺利,直到我采用'GPUImage',第三方api.我被告知这个api不需要多线程或单独排队,因为它全部都在内部处理.所以我完全取消了'sessionQueue'.

但是,现在我的应用程序运行起来非常不稳定,我认为这是由于主队列被告知处理大多数分支任务.

我可以有一个单独的队列来观察self.videoCamera的变化吗?这会占用mainQueue的大部分负担吗?

mat*_*att 5

坚持,那里,gizmodo!我没有说(我认为你的意思是我)"不需要多线程或单独排队".我说我不相信你在之前的问题中实际显示的(微小)代码中需要它.

而且你也完全正确,Apple直接建议在后台线程上启动捕获会话.正如他们在AVCamManual示例代码中的评论明确指出:

-[AVCaptureSession startRunning]阻止通话可能需要很长时间.我们将会话设置分派给sessionQueue,以便不阻止主队列(这使得UI保持响应).

到现在为止还挺好.但我也说过,我坚持这一点:多线程很难.

我们以这个新问题中的代码为例.你是说:

 dispatch_async([self sessionQueue], ^{
      [[self session] stopRunning];
      [self removeObservers];
 });
Run Code Online (Sandbox Code Playgroud)

现在,这可能是一件好事,然后再说它可能不会.在Apple的示例代码中,决定在后台线程上启动捕获会话后,他们会小心地从那时起在该线程(队列)上触摸该捕获会话.而你似乎也在做同样的事情.非常好.

但这不是你在后台线程中所做的全部.removeObservers例如,我怎么知道你的方法会发生什么?如果它触及任何属性self或任何其他对象,或者它调用任何方法,或者它调用Cocoa的任何非线程安全的部分(事实上,它可能是Cocoa的大部分),那么你是当事情神秘而且不可理喻地出错时,我会走向严重的麻烦 - 如果不适合你,那么(甚至更糟)某些用户.(当然,我省略,因为被简单地认为,这样做的危险,任何连接与应用程序的任何,但主线程接口的任何方式.)

我怎么知道你在代码的其他部分做了什么?Apple [self session] 在这一个后台线程中小心触摸; 这是一个重要的规则,是良好的多线程涉及的一部分.但知道这个规则吗?难道永远做触摸的错误[self session]主线程或其他线程从这个不同呢?我怎么知道?我不.

所以,再次总结一下,使用你想要的多线程,只要你知道自己在做什么,只要你准备好承担后果.多线程很难.(哎呀,我又说了一遍.)

现在,也许你已经彻底审查了你的removeObservers方法(以及你在这里从后台线程调用的所有其他方法).我猜这removeObservers可能直接在Apple的示例代码中复制模型,在这种情况下,一切都可能正常.也许你是一个很棒的多线程阅读器,我在这里所说的一切都是众所周知的,只是像鸭子背上的水一样洗掉.那很棒!那么这些问题对你来说不是问题,你应该忽视我的话.简而言之,您可以并且可能应该使用后台线程来处理捕获会话,只要您知道自己在做什么并且不要超出安全范围.如果你知道那些界限是什么,太棒了!我的警告是,而且,以防你知道.