我正在尝试取消然后释放暂停的计时器但是当我调用'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块中调用dispatch_suspend吗?
任何帮助都将不胜感激。
答案 0 :(得分:30)
崩溃的原因是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:
您可以暂停和恢复调度源事件的传递 暂时使用dispatch_suspend和dispatch_resume方法。 这些方法增加和减少你的暂停计数 派遣对象。因此,您必须平衡每次通话 dispatch_suspend,在事件发生之前匹配对dispatch_resume的调用 送货恢复。
虽然这并没有说你不能发布一个被暂停的调度源,但是它确实说你必须平衡每个调用,所以我假设它是使用一个调度信号量下面的东西。引擎盖必须是balanced before they can be released。这只是我的猜测: - )。
至于“我可以在定时器源的event_handler块中调用dispatch_suspend”。我很确定你可以,是的,根据dispatch_suspend
的文档:
在完成呼叫时运行的任何阻止后,将暂停。