On Aug 14, 2015, at 8:07 PM, Carl Hoefs <[email protected]> wrote:
> Here's what I'm trying to do, but in code rather than words:
>
> . . .
> [self doStatusChecks]; // start endless checking at 1-min intervals
> . . .
>
>
> - (void)doStatusChecks
> {
> [jobQueue addOperation:[[NSInvocationOperation alloc] initWithTarget:self
> selector:@selector(checkStatus) object:nil]];
> }
>
> - (void)checkStatus
> {
> // Access device & read status
> // If bad, do work...
>
> // Enqueue another operation, but after 60 sec delay
>
> [self performSelector:@selector(doStatusChecks)
> withObject:nil
> afterDelay:60.0]; // <-- This never fires!
>
> [self doStatusChecks]; // <-- Fires immediately, but not what I want
> }
-performSelector:withObject:afterDelay: depends on the run loop. The threads
that service any non-main NSOperationQueue don't run their run loop. In fact,
you can't rely on them surviving past the end of your operation's code
returning.
You will need to shunt this to a thread which reliably runs its run loop. The
obvious candidate is the main thread.
You could do some combination of
-performSelectorOnMainThread:withObject:waitUntilDone: with
-performSelector:withObject:afterDelay:, but it's really much simpler to use
GCD.
One approach is to use dispatch_after(). You could schedule a task to invoke
-doStatusChecks on the main thread:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 60ULL * NSEC_PER_SEC),
dispatch_get_main_queue(), ^{
[self doStatusChecks];
});
Depending on why you're using a custom operation queue, you might skip the
middle man and do:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 60ULL * NSEC_PER_SEC),
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self checkStatus];
});
Finally, since this is a recurring task, you can use a dispatch timer source to
do it all:
dispatch_source_t timer =
dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 60ULL * NSEC_PER_SEC,
1ULL * NSEC_PER_SEC);
dispatch_source_set_event_handler(timer, ^{
[self checkStatus];
});
dispatch_resume(timer);
Regards,
Ken
_______________________________________________
Cocoa-dev mailing list ([email protected])
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com
This email sent to [email protected]