Objective c 我在q1上的dispatch_async调用了主队列上的UI对象,它在q1上添加了回调,崩溃了
听起来很混乱,但看起来是这样的Objective c 我在q1上的dispatch_async调用了主队列上的UI对象,它在q1上添加了回调,崩溃了,objective-c,multithreading,objective-c-blocks,grand-central-dispatch,Objective C,Multithreading,Objective C Blocks,Grand Central Dispatch,听起来很混乱,但看起来是这样的 AVPlayer *capturedPlayer = _player; dispatch_async(_subtitlesQueue, ^{ // Parse the requested subtitle track and create a subtitle time observer subripString = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringE
AVPlayer *capturedPlayer = _player;
dispatch_async(_subtitlesQueue, ^{
// Parse the requested subtitle track and create a subtitle time observer
subripString = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
subripEntries = [SubRipParser parse:subripString];
if (!subripEntries.count)
return;
dispatch_async(dispatch_get_main_queue(), ^{
_subtitlesTimeObserver = [capturedPlayer addPeriodicTimeObserverForInterval:CMTimeMake(1, 5)
queue:_subtitlesQueue
usingBlock:^(CMTime time){}];
});
});
单击按钮时调用上述代码。它崩溃了。我对GCD和整个排队系统都是新手,所以也许我有点误解,但上面的工作不应该吗
如果我将主队列上的调用更改为同步调用,那么它就会工作。崩溃发生在对AVPlayer的makePeriodicCall(或类似)的调用的子标题队列中
如果我将周期时间观察程序添加到主队列而不是自定义串行队列,则异步调用也可以工作。然而,文档说添加到不同的队列应该是可以的
问题2)
当我在这里的时候,我也有一个关于“捕获”AVPlayer的部分的问题。这样捕获变量是否足够安全,还是我必须使用_弱并确保它在块中不为NULL?我的情况是,包含AVPlayer的控制器是单例的,因此它在应用程序的整个生命周期中都存在。我认为这使得不使用_弱修饰符可以。我这样想对吗
干杯,谢谢你的帮助
编辑:
例外情况是EXC_BAD_访问代码2,因此不应该访问的内容是。它发生在运行_subtitlesque的单独线程上。它发生在对[AVPlayerPeriodicCaller\u effectiveRateChanged]的调用中
在调用addPeriodicTimeObserver之前,我还打印了CapturedLayer和_SubtitleQueue(指针值)的值,在调用_SubtitleQueue上的外部调度异步之前,在调用主队列上的内部调度异步之前,以及在调用addPeriodicTimeObserver上的调度异步内部。他们都一样
编辑2:
如果我在队列上的周期性时间观察者创建周围添加一个同步块,那么事情就正常了
@synchronized(_subtitlesQueue) {
_subtitlesTimeObserver = [capturedPlayer addPeriodicTimeObserverForInterval:CMTimeMake(1, 5)
queue:_subtitlesQueue
usingBlock:subtitleTimeObservedBlock];
}
当您向正在播放的AVPlayer添加定期观察者时,-[AVPlayerPeriodicCaller\u effectiveRateChanged]
中似乎出现了所有内容。我正在使用的解决方法是:
BOOL playing = player.rate > 0.0f;
if (playing)
{
[player pause];
}
[player addPeriodicTimeObserverForTimeInterval:myTime queue:mySerialQueue usingBlock:myBlock];
if (playing)
{
[player play];
}
正如您所指出的,另一种解决方法是传递NULL
而不是串行队列,因为这会使块在主线程调度队列上排队。当您向正在播放的AVPlayer添加定期观察者时,-[AVPlayerPeriodicCaller\u effectiviverateChanged]
。我正在使用的解决方法是:
BOOL playing = player.rate > 0.0f;
if (playing)
{
[player pause];
}
[player addPeriodicTimeObserverForTimeInterval:myTime queue:mySerialQueue usingBlock:myBlock];
if (playing)
{
[player play];
}
正如您所指出的,另一种解决方法是传递
NULL
而不是串行队列,因为这会使主线程调度队列上的块排队。subtitlesQueue是局部变量吗?实例变量?它是什么时候创建和发布的?\u subtitlesque是在初始化视图控制器时创建的成员变量。哦,它的发布应该由ARC处理(从ios6开始)。您能否提供一个显示问题的小型但自包含的示例程序?\u subtitlesque
是局部变量吗?实例变量?它是何时创建和发布的?\u subtitlesQueue是在初始化视图控制器时创建的成员变量。哦,它的发布应该由ARC处理(从ios6开始)。您能否提供一个小型但自包含的示例程序来显示问题?感谢erikprice,这已经是一个很长的时间了。从那时起,代码已经改变了很多,所以我不能确认,但是很高兴知道:)谢谢erikprice,这已经是很长一段时间了。从那以后,代码发生了很大的变化,所以我无法确认,但很高兴知道:)