iOS AVFoundation和多线程
在Apple的AVFoundation演示的每个示例代码中,都有一个用于所有会话任务的独立队列iOS AVFoundation和多线程,ios,multithreading,avfoundation,grand-central-dispatch,gpuimage,Ios,Multithreading,Avfoundation,Grand Central Dispatch,Gpuimage,在Apple的AVFoundation演示的每个示例代码中,都有一个用于所有会话任务的独立队列 dispatch_queue_t sessionQueue = dispatch_queue_create("session queue", DISPATCH_QUEUE_SERIAL); 这也用于观察焦点变化、曝光变化、白平衡变化等: - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated];
dispatch_queue_t sessionQueue = dispatch_queue_create("session queue", DISPATCH_QUEUE_SERIAL);
这也用于观察焦点变化、曝光变化、白平衡变化等:
- (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];
}
当我遵循这一点时,一切都很顺利,直到我采用了第三方api“GPUImage”。我被告知,这个api不需要多线程或单独排队,因为它都在内部处理。所以我把“会话队列”完全去掉了
然而,现在我的应用程序运行起来真的很不稳定,我想这是因为主队列告诉我要处理大多数分支任务
我可以单独排队只为了观察摄像机的变化吗?这会不会减少主队列的大部分负载?等等,gizmodo!我没有说(我想你是指我)“不需要多线程或单独排队”。我说我不相信你在前面的问题中实际展示的(微小的)代码中需要它 你也完全正确,苹果直接建议在后台线程上启动捕获会话。正如他们在报纸上的评论明确指出的那样:
-[AVCaptureSession startRunning]
是一个阻塞调用,可能需要很长时间。我们将会话设置分派到sessionQueue,这样主队列就不会被阻塞(这会使UI保持响应)
到目前为止,一切顺利。但我也说过,我坚持这一点:多线程很难
让我们以这个新问题中的代码为例。你是说:
dispatch_async([self sessionQueue], ^{
[[self session] stopRunning];
[self removeObservers];
});
现在,这可能是一个好的说法,但也可能不是。在苹果的示例代码中,决定在后台线程上启动捕获会话后,他们会小心地从那时起只在该线程(队列)上触摸该捕获会话。你似乎也在做同样的事。那很好
但这并不是你在后台线程中所做的全部。例如,我如何知道removeObservers
方法中发生了什么?如果它涉及到self
或任何其他对象的任何属性,或者如果它调用了任何这样做的方法,或者如果它调用了Cocoa中不安全的任何部分(事实上,这可能是Cocoa的大部分),那么当事情神秘而不可预知地出错时,您将面临严重的麻烦-如果不是为您,那么(甚至更糟)对于某些用户。(当然,我只是简单地假设,我忽略了在除主线程之外的任何线程上以任何方式连接应用程序接口的任何操作的危险。)
我怎么知道你在代码的其他部分还做了什么?苹果只在这一个后台线程中小心地触摸[self session]
;这是一条重要的规则,也是好的多线程所涉及的一部分。但是你知道这个规则吗?您是否曾经在主线程或与此线程不同的其他线程上触碰过[self session]
?我怎么知道?我不知道
因此,再一次总结一下,只要您知道自己在做什么,并且准备好承担后果,就可以随心所欲地使用多线程。多线程是很难的。(哎呀,我再说一遍。)
现在,也许您已经彻底检查了
removeObservers
方法(以及您在这里从后台线程调用的所有其他方法)。我猜removeObservators
可能直接复制了苹果示例代码中的模型,在这种情况下,一切可能都很好。也许你是一个很棒的多线程程序,我在这里所说的一切对你来说都是众所周知的,就像鸭子背上的水一样。太好了!那么这些担忧对你来说不是问题,你应该无视我的话。简言之,您可以而且可能应该使用后台线程来处理捕获会话,只要您知道自己在做什么,并且不超出安全范围。如果你知道这些界限是什么,太棒了!我的警告过去是,现在也是,以防万一你不知道 请记住,当涉及到编码时,我的知识和技能水平与你相差甚远。我一直在关注苹果公司自己的关于AVFoundation的示例代码项目,即“AVCam”。在那里,有一个处理会话和观察者的“会话队列”(焦点机会、曝光变化、白平衡变化等)。随着GPUImage的采用,我不确定是否应该有单独的队列。如果我有,我对如何采用它来处理GPUImage感到困惑。除此之外,我还有一个实时直方图(GPUHistogram),显示在一个单独的GPUImage上,在主摄像头预览窗口的顶部,它使主摄像头预览放下帧。所以我认为将某些任务分开可以解决这个问题…我也会对此感到困惑!这就是我要警告你的。是的,你不想放下帧,但要避免这一点很难。这就是我要说的。matt、 我想问一下具体情况,并指出GPUImage部分中我遇到问题的确切部分。我应该在这里开始一个新问题吗?在Github上提问吗?你会推荐什么?我认为你可以两者兼而有之。:)我不使用GPUImage,但我很确定这里的很多人都使用。但总的来说,我的建议是告诉你自己让你的应用程序多线程化,这样你就可以自信地去做了。