iphone - dispatch_source_cancel en un temporizador suspendido causa EXC_BAD_INSTRUCTION
ios ios5 (1)
La razón por la que se bloquea es debido a este código :
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);
}
Por lo tanto, no puede liberar un dispatch_source_t
que ha sido suspendido. Probablemente no quieras simplemente suspenderlo en resetTimer
, supongo.
Aunque no puedo encontrar nada en los documentos por qué lo han escrito así (y el comentario alude a los pros y los contras de estar en un radar que nunca veremos), todo lo que puedo hacer es referirme a los documentos en los que dice :
Puede suspender y reanudar temporalmente la entrega de eventos de origen de despacho utilizando los métodos dispatch_suspend y dispatch_resume. Estos métodos incrementan y disminuyen el recuento de suspensiones para su objeto de despacho. Como resultado, debe equilibrar cada llamada a dispatch_suspend con una llamada coincidente a dispatch_resume antes de que se reanude la entrega del evento.
Si bien eso no dice que no se puede liberar una fuente de despacho que se ha suspendido, sí que se debe equilibrar cada llamada, así que supongo que es algo parecido a usar un semáforo debajo del capó que tiene para ser equilibrados antes de que puedan ser liberados . Eso es solo mi conjetura sin embargo :-).
En cuanto a "puedo invocar dispatch_suspend dentro del bloque event_handler de una fuente del temporizador". Estoy bastante seguro de que puede, sí, según los documentos para dispatch_suspend
:
La suspensión se produce después de la finalización de los bloques que se ejecutan en el momento de la llamada.
Estoy intentando cancelar y luego liberar un temporizador suspendido, pero cuando invoco ''dispatch_release'' en él, inmediatamente obtengo EXC_BAD_INSTRUCTION.
¿No es este un conjunto válido de acciones para tomar en un temporizador?
Creación y suspensión del temporizador:
@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
Además, ¿puedo invocar dispatch_suspend dentro del bloque event_handler de una fuente del temporizador?
Cualquier ayuda sería apreciada.