暂停计时器上的dispatch_source_cancel会导致EXC_BAD_INSTRUCTION

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

这是不是一个有效的计时器行动?

计时器创build和暂停:

@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块内的dispatch_suspend吗?

任何帮助,将不胜感激。

它崩溃的原因是因为这个代码 :

 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挂起它。

虽然我找不到文档中的任何内容,为什么他们这样写(这个评论暗示我们永远不会看到正面和负面的雷达),我所能做的就是参考文档说 :

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

虽然这并不是说你不能发布一个已经被暂停的调度源,但它确实说你必须平衡每个调用,所以我假设它是沿着它的东西使用调度信号灯下的东西在被释放前平衡 。 这只是我的猜测,但:-)。

至于“我可以在一个定时器源的event_handler块中调用dispatch_suspend”。 我敢肯定,你可以,根据dispatch_suspend的文档:

在通话结束后,发生中断。

Interesting Posts