iphone - 暂停计时器上的 dispatch_source_cancel 导致 EXC_BAD_INSTRUCTION

标签 iphone ios ios5 grand-central-dispatch dispatchertimer

我试图取消然后释放暂停的计时器,但是当我对其调用“dispatch_release”时,我立即收到 EXC_BAD_INSTRUCTION。

这不是对计时器采取的一组有效操作吗?

定时器的创建和暂停:

@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

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

如有任何帮助,我们将不胜感激。

最佳答案

它崩溃的原因是因为 this code :

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 中暂停它。

虽然我在文档中找不到任何关于他们为什么这样写的内容(并且评论暗示了我们永远不会看到的雷达中的利弊),但我所能做的就是引用docs where it says :

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.

虽然这并没有说你不能释放一个被挂起的调度源,它确实说你必须平衡每个调用所以我假设它是在使用调度信号量的情况下-引擎盖必须是balanced before they can be released .不过这只是我的猜测 :-)。

至于“我可以在定时器源的事件处理程序 block 中调用 dispatch_suspend”吗?我很确定你可以,是的,根据 dispatch_suspend 的文档:

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

关于iphone - 暂停计时器上的 dispatch_source_cancel 导致 EXC_BAD_INSTRUCTION,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9572055/

相关文章:

ios - 使用 Storyboards 时如何让 UITable header 贴在屏幕顶部?

iphone - 如何在 UITextView 中插入 UIImageView,就像 iphone 默认消息 (SMS) 应用程序在 UITextView 中插入多媒体内容一样

iphone - 我应该保存在 plist 还是 Core Data 中?

iphone - #import "test.h"与 #import <test.h>

iphone - 关于流体布局的问题

ios - 单例方法停止 iOS 中的代码执行

ios - 在 iOS Swift 3 中使用 UISplitViewController

iphone - UITextField - 圆角问题

iphone - 将 UILabel 名称引用为变量

iphone:无法连接 socket ?