On Aug 14, 2015, at 8:43 PM, Carl Hoefs <newsli...@autonomy.caltech.edu> wrote:
> On Aug 14, 2015, at 6:24 PM, Ken Thomases <k...@codeweavers.com> wrote: >> >> -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); >> > > Thanks, Ken. The reason I'm using a custom operation queue instead of GCD is > that I need to permit only exclusive access to the device (e.g., to obtain > its status requires writing to it), but allow other operations enqueued to > use the device, not just the status checks. So I have an NSOperationQueue > that has maxConcurrentOperationCount set to 1, but I need a status-check > operation to be automatically queued up 1 minute after the last one has run. > > So, if the device is accessed otherwise the status checks won't interfere > with that because only 1 operation can be active in the queue, thus > everything stays well ordered and exclusive access is permitted to all, one > at a time. I just can't figure a way to have the status check operation > trigger another one to be magically enqueued 60 seconds later. You can use a serial GCD queue for the same purpose with my above suggestions. But even if you want to keep using an NSOperationQueue, you can still use my first dispatch_after() suggestion. It works just like your code except for replacing -performSelector:withObject:afterDelay: with dispatch_after(). This changes doesn't affect anything about how -doStatusChecks works. It will still use your NSOperationQueue. You don't need to use the main GCD queue for my dispatch_after() suggestion, you can use a global concurrent queue. Either works. 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