On Aug 14, 2015, at 8:07 PM, Carl Hoefs <newsli...@autonomy.caltech.edu> 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 (Cocoa-dev@lists.apple.com)

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 arch...@mail-archive.com

Reply via email to