Re: NSPrivateQueueConcurrencyType working outside of performBlock
Re: NSPrivateQueueConcurrencyType working outside of performBlock
- Subject: Re: NSPrivateQueueConcurrencyType working outside of performBlock
- From: Roland King <email@hidden>
- Date: Tue, 28 Jul 2015 22:29:46 +0800
> On 28 Jul 2015, at 10:14 pm, Trygve Inda <email@hidden> wrote:
>
>>
>>> On 28 Jul 2015, at 9:12 pm, Trygve Inda <email@hidden> wrote:
>>>
>>> I gather that when using NSPrivateQueueConcurrencyType, all operations (a
>>> fetch for example) have to be done within a performBlock call.
>>>
>>
>> ...
>>
>>> Then later, this context is used outside a performBlock:
>>>
>>>
>>> NSArray *matchingQuakes = [taskContext
>>> executeFetchRequest:matchingQuakeRequest error:&anyError];
>>>
>>>
>>> Why does this work?
>>
>> You are supposed to call performBlock so that all accesses to the MOC are
>> serialized on the queue and so you get thread safety that way. However it's
>> quite possible to call the methods directly on the MOC in any thread context
>> and they will work, all the performBlock() actually does is queue the same
>> block of code onto the dispatch queue and when it's its turn, it executes by
>> calling [ moc executeFetch.. blah blah].
>>
>> If you do that of course you have no thread safety any more and are likely to
>> blow up. In this case there's only one thread (I believe) and so the accesses
>> are serialized anyway and it works. It's a bad piece of code.
>>
>> I filed an enhancement report requesting that the coredata stack assert if you
>> called a private queue MOC method from the wrong queue, I don't recall seeing
>> anything come of it, however I do remember there is quite a lot of logging you
>> can turn up on CoreData and it's possible one such log will tell you you're
>> doing this.
>
> If I do use performBlock and have to do several things:
>
> This code is sitting inside a completion block for a URL downloader
> {
> [self doSomething];
> [myContext performBlock (do more stuff)];
> [self doSomethingElse];
> }
>
>
> Since the perform block will run in a different thread, how can I make sure
> the "do more stuff" is finished before calling doSomethingElse?
>
> Or in this case would using NSConfinementConcurrencyType be better since it
> is all within a completion block and presumably on it's own thread anyway.
>
Put the [ self doSomethingElse ] inside the block you are performing (do more stuff) as the last thing
ie
[ self doSomething ]
[ myContext performBlock: { do more stuff ; [ self doSomethingElse ] }
if you have to flip back to the main thread or another queue, then dispatch_async it back at the end. The beauty of blocks is you can do this, although the indentation gets a bit gnarly.
NSConfinementConcurrencyType has had its day and is deprecated in 10.11 so I wouldn't recommend it for new code.
_______________________________________________
Cocoa-dev mailing list (email@hidden)
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:
This email sent to email@hidden