暂停计时器上的dispatch_source_cancel会导致EXC_BAD_INSTRUCTION [英] dispatch_source_cancel on a suspended timer causes EXC_BAD_INSTRUCTION

查看:2038
本文介绍了暂停计时器上的dispatch_source_cancel会导致EXC_BAD_INSTRUCTION的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试取消然后释放暂停的计时器但是当我调用'dispatch_release'时,我立即得到EXC_BAD_INSTRUCTION。

I'm trying to cancel and then release a suspended timer but when I invoke 'dispatch_release' on it, I immediately get EXC_BAD_INSTRUCTION.

这不是一套有效的定时器动作吗?

Is this not a valid set of actions to take on a timer?

定时器创建&暂停:

Timer creation & suspension:

@interface SomeClass: NSObject { }
@property (nonatomic, assign) dispatch_source_t             timer;
@end

// Class implementation
@implementation SomeClass

@synthesize timer = _timer;

- (void)startTimer 
{
    dispatch_queue_t globalQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 
                                    0, 0, globalQ); 

    dispatch_time_t startWhen = dispatch_walltime(DISPATCH_TIME_NOW, NSEC_PER_SEC * 1);
    dispatch_source_set_timer(_timer, startWhen, 1 * NSEC_PER_SEC, 5000ull);

    dispatch_source_set_event_handler(_timer, ^{
        // Perform a task 

        // If a particular amount of time has elapsed, kill this timer
        if (timeConstraintReached)
        {
            // Can I suspend this timer within it's own event handler block?
            dispatch_suspend(_timer);
        }
    });

    dispatch_resume(_timer);
}

- (void)resetTimer
{
    dispatch_suspend(_timer);

    dispatch_source_cancel(_timer);

    // dispatch_release causes 
    // 'EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
    dispatch_release(_timer);

    self.timer = nil;    
}
@end

此外,我可以在定时器源中调用dispatch_suspend吗? event_handler block?

Additionally, can I invoke dispatch_suspend within a timer source's event_handler block?

任何帮助都将不胜感激。

Any help would be appreciated.

推荐答案

崩溃的原因是此代码

void
_dispatch_source_xref_release(dispatch_source_t ds)
{
    if (slowpath(DISPATCH_OBJECT_SUSPENDED(ds))) {
        // Arguments for and against this assert are within 6705399
        DISPATCH_CLIENT_CRASH("Release of a suspended object");
    }
    _dispatch_wakeup(ds);
    _dispatch_release(ds);
}

所以,你不能发布 dispatch_source_t 已被暂停。你可能只是想暂停它在 resetTimer 我想。

So, you can't release a dispatch_source_t that has been suspended. You probably want to just not suspend it in resetTimer I guess.

虽然我找不到任何东西他们为什么写这样的文档(并且评论暗示利弊是我们永远不会看到的雷达),我所能做的就是参考 docs where words

Whilst I can't find anything in the docs for why they have written it like this (and the comment alludes to the pros and cons being in a radar we'll never see), all I can do is refer to the docs where it says:

您可以使用dispatch_suspend和dispatch_resume方法临时暂停和恢复调度源事件
的传递。
这些方法递增和递减
dispatch对象的挂起计数。因此,在事件
交付恢复之前,您必须平衡每次调用
dispatch_suspend以及对dispatch_resume的匹配调用。

You can suspend and resume the delivery of dispatch source events temporarily using the dispatch_suspend and dispatch_resume methods. These methods increment and decrement the suspend count for your dispatch object. As a result, you must balance each call to dispatch_suspend with a matching call to dispatch_resume before event delivery resumes.

虽然这并没有说你不能发布一个被暂停的调度源,但是它确实说你必须平衡每个调用,所以我假设它是使用一个调度信号量下面的东西。引擎盖必须才能发布。这只是我的猜测: - )。

Whilst that doesn't say you can't release a dispatch source that's been suspended, it does say you have to balance each call so I'm assuming it's something along the lines of it's using a dispatch semaphore under-the-hood which have to be balanced before they can be released. That's just my guess though :-).

至于我可以在定时器源的event_handler块中调用dispatch_suspend。我很确定你可以,是的,根据 dispatch_suspend 的文档:

As for "can I invoke dispatch_suspend within a timer source's event_handler block". I'm pretty sure you can, yes, as per the docs for dispatch_suspend:


在完成通话时运行的任何块之后发生暂停。

The suspension occurs after completion of any blocks running at the time of the call.

这篇关于暂停计时器上的dispatch_source_cancel会导致EXC_BAD_INSTRUCTION的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆