On Apr 4, 2010, at 11:00 PM, Jerry Krinock wrote:
> On 2010 Apr 04, at 14:44, Ken Thomases wrote:
>
>> Since you're already using operations, why use the above 'while' loop,
>> anyway? Why not use -[NSOperationQueue waitUntilAllOperationsAreFinished].
>> Or schedule a "sentinel" operation that depends on all of the other
>> operations, either directly or indirectly, and then invoke
>> -waitUntilFinished on it.
>
> Alas, many of my operations call back to perform Core Data operations on the
> main thread. (Syncing multiple managed object contexts never looked like
> much fun to me.) The disadvantage is that this nice, clean approach you
> suggest results in deadlock.
Ah, yes. This approach won't work in that case.
> - (void)tickleRunLoop {
> // No op
> }
>
> /* This method is called from the -main of the final NSOperation
> in an Agent task. Like all NSOperations, it's running on a
> secondary thread. */
> - (void)terminateWork {
> // Set the exit condition for Worker
> [[AgentPerformer sharedPerformer] setIsDone:YES] ;
>
> // Now install an input source on the main run loop, so that
> // in Worker-main.m, in main(), -runLoop:beforeDate: will
> // unblock, the above exit condition will be tested, found
> // to be true, and cause the loop to break so that Worker
> // can continue along to exit.
> [self performSelectorOnMainThread:@selector(tickleRunLoop)
> withObject:nil
> waitUntilDone:YES] ;
> }
>
> This is actually a simple modification of the code at the end of my original
> post, except that now we remember to call back to the main thread -- Thank
> you, Ken!
You're welcome.
> I'm happy with this, although I suspect someone might suggest something less
> kludgey.
You might have -terminateWork only do the -setIsDone: step. Then, instead of
the operation's -main directly invoking -terminateWork, it could perform it on
the main thread. That way, the setting of isDone is actually happening on the
main thread, plus it serves as its own "tickle" of the run loop.
Also, there's no need to pass YES for the waitUntilDone: parameter. Since this
is the last thing you need to be done on the background thread, there's no need
to be sure it's complete before exiting. In general, it's best to avoid
blocking the worker threads managed for your by NSOperationQueue or GCD.
> I still wonder why my original code exitted after a 60-second timeout, though.
Well, the run loop documentation specifically warns that you can't be sure that
your input sources are the only input sources in the run loop. The frameworks
may put their own input sources there, too.
In this case, my guess is that it was the last worker thread timing out from
waiting for work, and shutting itself down. It may have performed some
internal selector on NSOperationQueue on the main thread, to inform it that the
worker thread had terminated.
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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com
This email sent to [email protected]