我在q1上调度dispatch_async,调用主队列上的UI对象,在q1上添加回调,崩溃

时间:2022-05-15 20:59:24

It sounds confusing but it looks like this

这看起来很混乱,但看起来像这样

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){}];
    });
});

The above piece of code is called when a button is clicked. It crashes. I'm new to GCD and the whole queue thing so perhaps I'm misunderstanding, but shouldn't the above work?

单击按钮时会调用上面的代码。它崩溃了。我是新手GCD和整个队列的事情,所以也许我是误解,但不应该上面的工作吗?

If I change the call on the main queue to a synchronous then it works. The crash happens from the subtitleQueue on a call to AVPlayer's makePeriodicCall (or the like).

如果我将主队列上的呼叫更改为同步,则它可以正常工作。在调用AVPlayer的makePeriodicCall(或类似函数)时,从subtitleQueue发生崩溃。

The async call also works if I add the periodic time observer to the main queue instead of custom serial queue. However, the docs say that adding on a different queue should be ok.

如果我将周期性时间观察器添加到主队列而不是自定义串行队列,则异步调用也可以。但是,文档说添加不同的队列应该没问题。

Question 2) And while I'm here, I also have a question about the part that "captures" the AVPlayer. Is capturing the variable like that safe enough or do I have to use __weak and make sure it's not NULL within the block? My situation is such that the controller that contains the AVPlayer is a singleton, so it exists throughout the lifetime of the application. I think this makes not using the __weak modifier ok. Am I correct in thinking this?

问题2)当我在这里时,我也有一个关于“捕获”AVPlayer的部分的问题。是否足够安全地捕获变量或者我是否必须使用__weak并确保它在块内不是NULL?我的情况是包含AVPlayer的控制器是一个单独的,因此它在应用程序的整个生命周期中都存在。我认为这不会使用__weak修饰符。我在想这个是正确的吗?

Cheers, and thanks for any help!

干杯,谢谢你的帮助!

EDIT: The exception is a EXC_BAD_ACCESS code 2, so something which shouldn't be accessed is. It happens on a separate thread that is running the _subtitlesQueue. And it happens on a call to [AVPlayerPeriodicCaller _effectiveRateChanged]

编辑:例外是EXC_BAD_ACCESS代码2,所以不应该访问的是。它发生在运行_subtitlesQueue的单独线程上。它发生在[AVPlayerPeriodicCaller _effectiveRateChanged]的调用上

I also printed out the values for the capturedPlayer and _subtitlesQueue (pointer values) before the outer dispatch_async is called on the _subtitlesQueue, before the inner dispatch_async is called on the main queue and inside the dispatch_async on the main queue before the addPeriodicTimeObserver is called. They are all the same.

在调用addPeriodicTimeObserver之前,在主队列上调用内部dispatch_async之前和主队列上的dispatch_async之前,我还在_subtitlesQueue上调用外部dispatch_async之前打印出capturePlayer和_subtitlesQueue(指针值)的值。他们都是一样的。

EDIT2: If I add a synchronized block around the periodic time observer creation on the subtitleQueue then things work...

EDIT2:如果我在subtitleQueue上创建周期性时间观察器周围添加一个synchronized块,那么事情就可以了......

@synchronized(_subtitlesQueue) {
    _subtitlesTimeObserver = [capturedPlayer addPeriodicTimeObserverForInterval:CMTimeMake(1, 5)
                                                                          queue:_subtitlesQueue
                                                                     usingBlock:subtitleTimeObservedBlock];
}

All

所有

1 个解决方案

#1


1  

There seems to be a bug that causes EXC_BAD_ACCESS in -[AVPlayerPeriodicCaller _effectiveRateChanged] when you add a periodic observer to a playing AVPlayer. The workaround that I'm using is:

当您向播放AVPlayer添加周期性观察者时,似乎有一个错误导致EXC_BAD_ACCESS - [AVPlayerPeriodicCaller _effectiveRateChanged]。我正在使用的解决方法是:

BOOL playing = player.rate > 0.0f;
if (playing)
{
    [player pause];
}

[player addPeriodicTimeObserverForTimeInterval:myTime queue:mySerialQueue usingBlock:myBlock];

if (playing)
{
    [player play];
}

As you pointed out, another workaround is to pass NULL instead of a serial queue, since that has the effect of enqueueing the blocks on the main thread dispatch queue.

正如您所指出的,另一种解决方法是传递NULL而不是串行队列,因为它具有在主线程调度队列上排队块的效果。

#1


1  

There seems to be a bug that causes EXC_BAD_ACCESS in -[AVPlayerPeriodicCaller _effectiveRateChanged] when you add a periodic observer to a playing AVPlayer. The workaround that I'm using is:

当您向播放AVPlayer添加周期性观察者时,似乎有一个错误导致EXC_BAD_ACCESS - [AVPlayerPeriodicCaller _effectiveRateChanged]。我正在使用的解决方法是:

BOOL playing = player.rate > 0.0f;
if (playing)
{
    [player pause];
}

[player addPeriodicTimeObserverForTimeInterval:myTime queue:mySerialQueue usingBlock:myBlock];

if (playing)
{
    [player play];
}

As you pointed out, another workaround is to pass NULL instead of a serial queue, since that has the effect of enqueueing the blocks on the main thread dispatch queue.

正如您所指出的,另一种解决方法是传递NULL而不是串行队列,因为它具有在主线程调度队列上排队块的效果。